@myerscarpenter/quest-dev 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,41 @@
1
+ name: Publish to npm
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ jobs:
9
+ test-and-publish:
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ contents: read
13
+ id-token: write # Required for OIDC trusted publishing
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - name: Setup Node.js
18
+ uses: actions/setup-node@v4
19
+ with:
20
+ node-version: 'lts/*'
21
+ registry-url: 'https://registry.npmjs.org'
22
+
23
+ - name: Install pnpm
24
+ uses: pnpm/action-setup@v4
25
+ with:
26
+ version: latest
27
+
28
+ - name: Install npm v11.6.2 (required for OIDC trusted publishing, min v11.5.1)
29
+ run: npm install -g npm@11.6.2
30
+
31
+ - name: Install dependencies
32
+ run: pnpm install
33
+
34
+ - name: Run tests
35
+ run: pnpm test
36
+
37
+ - name: Build
38
+ run: pnpm run build
39
+
40
+ - name: Publish to npm
41
+ run: npm publish --provenance --access public
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Quest open command
3
+ * Opens a URL in Quest browser with proper ADB port forwarding
4
+ */
5
+ /**
6
+ * Main open command handler
7
+ */
8
+ export declare function openCommand(url: string): Promise<void>;
9
+ //# sourceMappingURL=open.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open.d.ts","sourceRoot":"","sources":["../../src/commands/open.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAwFH;;GAEG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2C5D"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Quest open command
3
+ * Opens a URL in Quest browser with proper ADB port forwarding
4
+ */
5
+ import { checkADBPath, checkADBDevices, ensurePortForwarding, isBrowserRunning, launchBrowser, getCDPPort } from '../utils/adb.js';
6
+ import { execCommandFull } from '../utils/exec.js';
7
+ /**
8
+ * Try to navigate or reload existing tab via cdp-cli
9
+ */
10
+ async function tryNavigateExistingTab(targetUrl) {
11
+ const cdpPort = getCDPPort();
12
+ try {
13
+ // Get list of tabs using cdp-cli
14
+ const result = await execCommandFull('cdp-cli', ['--cdp-url', `http://localhost:${cdpPort}`, 'tabs']);
15
+ if (result.code !== 0) {
16
+ console.log('cdp-cli tabs command failed, will launch browser directly');
17
+ return false;
18
+ }
19
+ // Parse NDJSON output to find tabs
20
+ const lines = result.stdout.trim().split('\n').filter(line => line.trim());
21
+ const tabs = [];
22
+ for (const line of lines) {
23
+ try {
24
+ const tab = JSON.parse(line);
25
+ if (tab.id && tab.url !== undefined) {
26
+ tabs.push(tab);
27
+ }
28
+ }
29
+ catch {
30
+ // Skip non-JSON lines
31
+ }
32
+ }
33
+ // First, check if URL is already open
34
+ const existingTab = tabs.find(tab => tab.url === targetUrl);
35
+ if (existingTab) {
36
+ console.log(`Found existing tab with URL: ${targetUrl}`);
37
+ // Reload the tab
38
+ const reloadResult = await execCommandFull('cdp-cli', [
39
+ '--cdp-url', `http://localhost:${cdpPort}`,
40
+ 'go', existingTab.id, 'reload'
41
+ ]);
42
+ if (reloadResult.code === 0) {
43
+ console.log('Reloaded existing tab');
44
+ return true;
45
+ }
46
+ }
47
+ // Second, look for a blank tab to navigate
48
+ const blankTab = tabs.find(tab => tab.url === 'about:blank' ||
49
+ tab.url === 'chrome://newtab/' ||
50
+ tab.url === 'chrome://panel-app-nav/ntp' || // Quest New Tab page
51
+ tab.url === '');
52
+ if (blankTab) {
53
+ console.log('Found blank tab, navigating it...');
54
+ const navResult = await execCommandFull('cdp-cli', [
55
+ '--cdp-url', `http://localhost:${cdpPort}`,
56
+ 'go', blankTab.id, targetUrl
57
+ ]);
58
+ if (navResult.code === 0) {
59
+ console.log('Navigated blank tab to URL');
60
+ return true;
61
+ }
62
+ }
63
+ return false;
64
+ }
65
+ catch (error) {
66
+ console.log('CDP operation failed:', error.message);
67
+ return false;
68
+ }
69
+ }
70
+ /**
71
+ * Main open command handler
72
+ */
73
+ export async function openCommand(url) {
74
+ // Parse port from URL
75
+ let port;
76
+ try {
77
+ const parsedUrl = new URL(url);
78
+ port = parseInt(parsedUrl.port, 10);
79
+ if (!port || isNaN(port)) {
80
+ console.error('Error: Could not parse port from URL:', url);
81
+ process.exit(1);
82
+ }
83
+ }
84
+ catch (error) {
85
+ console.error('Error: Invalid URL:', url);
86
+ process.exit(1);
87
+ }
88
+ console.log(`\nOpening ${url} on Quest...\n`);
89
+ // Check prerequisites
90
+ checkADBPath();
91
+ await checkADBDevices();
92
+ // Set up port forwarding (idempotent)
93
+ await ensurePortForwarding(port);
94
+ // Check if browser is running
95
+ const browserRunning = await isBrowserRunning();
96
+ if (!browserRunning) {
97
+ console.log('Quest browser is not running');
98
+ await launchBrowser(url);
99
+ }
100
+ else {
101
+ console.log('Quest browser is already running');
102
+ // Try to navigate existing or blank tab via cdp-cli first
103
+ const navigated = await tryNavigateExistingTab(url);
104
+ if (!navigated) {
105
+ console.log('No existing or blank tab found, opening URL...');
106
+ await launchBrowser(url);
107
+ }
108
+ }
109
+ console.log('\nDone!\n');
110
+ }
111
+ //# sourceMappingURL=open.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open.js","sourceRoot":"","sources":["../../src/commands/open.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Quest screenshot command
3
+ * Triggers Quest's native screenshot service and pulls the file
4
+ */
5
+ /**
6
+ * Main screenshot command handler
7
+ */
8
+ export declare function screenshotCommand(outputPath: string): Promise<void>;
9
+ //# sourceMappingURL=screenshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screenshot.d.ts","sourceRoot":"","sources":["../../src/commands/screenshot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAiEH;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BzE"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Quest screenshot command
3
+ * Triggers Quest's native screenshot service and pulls the file
4
+ */
5
+ import { resolve } from 'path';
6
+ import { checkADBPath, checkADBDevices } from '../utils/adb.js';
7
+ import { execCommand } from '../utils/exec.js';
8
+ /**
9
+ * Trigger Quest screenshot service
10
+ */
11
+ async function triggerScreenshot() {
12
+ try {
13
+ await execCommand('adb', [
14
+ 'shell',
15
+ 'am',
16
+ 'startservice',
17
+ '-n',
18
+ 'com.oculus.metacam/.capture.CaptureService',
19
+ '-a',
20
+ 'TAKE_SCREENSHOT'
21
+ ]);
22
+ console.log('Screenshot service triggered');
23
+ return true;
24
+ }
25
+ catch (error) {
26
+ console.error('Failed to trigger screenshot:', error.message);
27
+ return false;
28
+ }
29
+ }
30
+ /**
31
+ * Get most recent screenshot filename from Quest
32
+ */
33
+ async function getMostRecentScreenshot() {
34
+ try {
35
+ const output = await execCommand('adb', ['shell', 'ls', '-t', '/sdcard/Oculus/Screenshots/']);
36
+ const files = output.split('\n').filter(line => line.trim() && line.endsWith('.jpg'));
37
+ if (files.length === 0) {
38
+ console.error('No screenshots found in /sdcard/Oculus/Screenshots/');
39
+ return null;
40
+ }
41
+ const mostRecent = files[0].trim();
42
+ console.log(`Found most recent screenshot: ${mostRecent}`);
43
+ return mostRecent;
44
+ }
45
+ catch (error) {
46
+ console.error('Failed to list screenshots:', error.message);
47
+ return null;
48
+ }
49
+ }
50
+ /**
51
+ * Pull screenshot from Quest to local path
52
+ */
53
+ async function pullScreenshot(filename, outputPath) {
54
+ try {
55
+ const remotePath = `/sdcard/Oculus/Screenshots/${filename}`;
56
+ await execCommand('adb', ['pull', remotePath, outputPath]);
57
+ console.log(`Screenshot saved to: ${outputPath}`);
58
+ return true;
59
+ }
60
+ catch (error) {
61
+ console.error('Failed to pull screenshot:', error.message);
62
+ return false;
63
+ }
64
+ }
65
+ /**
66
+ * Main screenshot command handler
67
+ */
68
+ export async function screenshotCommand(outputPath) {
69
+ const resolvedPath = resolve(outputPath);
70
+ console.log('\nQuest Screenshot\n');
71
+ // Check prerequisites
72
+ checkADBPath();
73
+ await checkADBDevices();
74
+ // Trigger screenshot
75
+ if (!await triggerScreenshot()) {
76
+ process.exit(1);
77
+ }
78
+ // Wait for screenshot to save
79
+ console.log('Waiting for screenshot to save...');
80
+ await new Promise(resolve => setTimeout(resolve, 2000));
81
+ // Get most recent screenshot
82
+ const filename = await getMostRecentScreenshot();
83
+ if (!filename) {
84
+ process.exit(1);
85
+ }
86
+ // Pull screenshot
87
+ if (!await pullScreenshot(filename, resolvedPath)) {
88
+ process.exit(1);
89
+ }
90
+ console.log('\nDone!\n');
91
+ }
92
+ //# sourceMappingURL=screenshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../../src/commands/screenshot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C;;GAEG;AACH,KAAK,UAAU,iBAAiB;IAC9B,IAAI,CAAC;QACH,MAAM,WAAW,CAAC,KAAK,EAAE;YACvB,OAAO;YACP,IAAI;YACJ,cAAc;YACd,IAAI;YACJ,4CAA4C;YAC5C,IAAI;YACJ,iBAAiB;SAClB,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAG,KAAe,CAAC,OAAO,CAAC,CAAC;QACzE,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,uBAAuB;IACpC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,6BAA6B,CAAC,CAAC,CAAC;QAC9F,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QAEtF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;YACrE,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,iCAAiC,UAAU,EAAE,CAAC,CAAC;QAC3D,OAAO,UAAU,CAAC;IACpB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAG,KAAe,CAAC,OAAO,CAAC,CAAC;QACvE,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,cAAc,CAAC,QAAgB,EAAE,UAAkB;IAChE,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,8BAA8B,QAAQ,EAAE,CAAC;QAC5D,MAAM,WAAW,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,wBAAwB,UAAU,EAAE,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAG,KAAe,CAAC,OAAO,CAAC,CAAC;QACtE,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,UAAkB;IACxD,MAAM,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAEzC,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IAEpC,sBAAsB;IACtB,YAAY,EAAE,CAAC;IACf,MAAM,eAAe,EAAE,CAAC;IAExB,qBAAqB;IACrB,IAAI,CAAC,MAAM,iBAAiB,EAAE,EAAE,CAAC;QAC/B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,8BAA8B;IAC9B,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;IACjD,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;IAExD,6BAA6B;IAC7B,MAAM,QAAQ,GAAG,MAAM,uBAAuB,EAAE,CAAC;IACjD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,kBAAkB;IAClB,IAAI,CAAC,MAAM,cAAc,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Quest Dev CLI
4
+ * Command-line tools for Meta Quest Browser development
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;GAGG"}
package/build/index.js ADDED
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Quest Dev CLI
4
+ * Command-line tools for Meta Quest Browser development
5
+ */
6
+ import yargs from 'yargs';
7
+ import { hideBin } from 'yargs/helpers';
8
+ import { readFileSync } from 'fs';
9
+ import { fileURLToPath } from 'url';
10
+ import { dirname, join } from 'path';
11
+ import { screenshotCommand } from './commands/screenshot.js';
12
+ import { openCommand } from './commands/open.js';
13
+ // Read version from package.json
14
+ const __dirname = dirname(fileURLToPath(import.meta.url));
15
+ const packageJson = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));
16
+ const version = packageJson.version;
17
+ // Create CLI
18
+ const cli = yargs(hideBin(process.argv))
19
+ .scriptName('quest-dev')
20
+ .version(version)
21
+ .usage('Usage: $0 <command> [options]')
22
+ .demandCommand(1, 'You must provide a command')
23
+ .strict()
24
+ .fail((msg, err, yargs) => {
25
+ if (msg) {
26
+ console.error(`Error: ${msg}\n`);
27
+ }
28
+ if (err) {
29
+ console.error(err.message);
30
+ }
31
+ console.error('Run "quest-dev --help" for usage information.');
32
+ process.exit(1);
33
+ })
34
+ .help()
35
+ .alias('help', 'h')
36
+ .epilog('Requires ADB to be installed and Quest connected via USB with debugging enabled.');
37
+ // Screenshot command
38
+ cli.command('screenshot <output>', 'Take a screenshot from Quest and save to local file', (yargs) => {
39
+ return yargs.positional('output', {
40
+ describe: 'Output file path (e.g., ~/screenshots/test.jpg)',
41
+ type: 'string',
42
+ demandOption: true
43
+ });
44
+ }, async (argv) => {
45
+ await screenshotCommand(argv.output);
46
+ });
47
+ // Open command
48
+ cli.command('open <url>', 'Open URL in Quest browser with ADB port forwarding', (yargs) => {
49
+ return yargs.positional('url', {
50
+ describe: 'URL to open (e.g., http://localhost:9004/myapp/)',
51
+ type: 'string',
52
+ demandOption: true
53
+ });
54
+ }, async (argv) => {
55
+ await openCommand(argv.url);
56
+ });
57
+ // Parse and execute
58
+ cli.parse();
59
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;GAGG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,iCAAiC;AACjC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAC5B,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAC1D,CAAC;AACF,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC;AAEpC,aAAa;AACb,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;KACrC,UAAU,CAAC,WAAW,CAAC;KACvB,OAAO,CAAC,OAAO,CAAC;KAChB,KAAK,CAAC,+BAA+B,CAAC;KACtC,aAAa,CAAC,CAAC,EAAE,4BAA4B,CAAC;KAC9C,MAAM,EAAE;KACR,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;IACxB,IAAI,GAAG,EAAE,CAAC;QACR,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IACnC,CAAC;IACD,IAAI,GAAG,EAAE,CAAC;QACR,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAC;IAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC;KACD,IAAI,EAAE;KACN,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC;KAClB,MAAM,CAAC,kFAAkF,CAAC,CAAC;AAE9F,qBAAqB;AACrB,GAAG,CAAC,OAAO,CACT,qBAAqB,EACrB,qDAAqD,EACrD,CAAC,KAAK,EAAE,EAAE;IACR,OAAO,KAAK,CAAC,UAAU,CAAC,QAAQ,EAAE;QAChC,QAAQ,EAAE,iDAAiD;QAC3D,IAAI,EAAE,QAAQ;QACd,YAAY,EAAE,IAAI;KACnB,CAAC,CAAC;AACL,CAAC,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;IACb,MAAM,iBAAiB,CAAC,IAAI,CAAC,MAAgB,CAAC,CAAC;AACjD,CAAC,CACF,CAAC;AAEF,eAAe;AACf,GAAG,CAAC,OAAO,CACT,YAAY,EACZ,oDAAoD,EACpD,CAAC,KAAK,EAAE,EAAE;IACR,OAAO,KAAK,CAAC,UAAU,CAAC,KAAK,EAAE;QAC7B,QAAQ,EAAE,kDAAkD;QAC5D,IAAI,EAAE,QAAQ;QACd,YAAY,EAAE,IAAI;KACnB,CAAC,CAAC;AACL,CAAC,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;IACb,MAAM,WAAW,CAAC,IAAI,CAAC,GAAa,CAAC,CAAC;AACxC,CAAC,CACF,CAAC;AAEF,oBAAoB;AACpB,GAAG,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * ADB utilities for Quest device communication
3
+ */
4
+ /**
5
+ * Check if ADB is available on PATH
6
+ */
7
+ export declare function checkADBPath(): string;
8
+ /**
9
+ * Check if ADB devices are connected (with auto-recovery for server issues)
10
+ */
11
+ export declare function checkADBDevices(retryCount?: number): Promise<boolean>;
12
+ /**
13
+ * Check if a port is already listening on localhost
14
+ */
15
+ export declare function isPortListening(port: number): Promise<boolean>;
16
+ /**
17
+ * Idempotently set up ADB port forwarding for a given port
18
+ */
19
+ export declare function ensurePortForwarding(port: number): Promise<void>;
20
+ /**
21
+ * Check if Quest browser is running
22
+ */
23
+ export declare function isBrowserRunning(): Promise<boolean>;
24
+ /**
25
+ * Launch Quest browser with a URL using am start
26
+ */
27
+ export declare function launchBrowser(url: string): Promise<boolean>;
28
+ /**
29
+ * Get CDP port
30
+ */
31
+ export declare function getCDPPort(): number;
32
+ //# sourceMappingURL=adb.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adb.d.ts","sourceRoot":"","sources":["../../src/utils/adb.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAkBrC;AAoBD;;GAEG;AACH,wBAAsB,eAAe,CAAC,UAAU,SAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAqCtE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAiB9D;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmCtE;AAED;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC,CAOzD;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAmBjE;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC"}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * ADB utilities for Quest device communication
3
+ */
4
+ import which from 'which';
5
+ import net from 'net';
6
+ import { execCommand, execCommandFull } from './exec.js';
7
+ const CDP_PORT = 9223; // Chrome DevTools Protocol port (Quest browser default)
8
+ /**
9
+ * Check if ADB is available on PATH
10
+ */
11
+ export function checkADBPath() {
12
+ try {
13
+ const adbPath = which.sync('adb');
14
+ console.log(`Found ADB at: ${adbPath}`);
15
+ return adbPath;
16
+ }
17
+ catch (error) {
18
+ console.error('Error: ADB not found in PATH');
19
+ console.error('');
20
+ console.error('Please install Android Platform Tools and add adb to your PATH:');
21
+ console.error('https://developer.android.com/tools/releases/platform-tools');
22
+ console.error('');
23
+ console.error('Installation instructions:');
24
+ console.error('- macOS: brew install android-platform-tools');
25
+ console.error('- Linux: sudo apt install adb (or equivalent)');
26
+ console.error('- Windows: Download from the link above and add to PATH');
27
+ console.error('');
28
+ process.exit(1);
29
+ }
30
+ }
31
+ /**
32
+ * Restart ADB server if it's in a bad state
33
+ */
34
+ async function restartADBServer() {
35
+ console.log('ADB server appears to be in a bad state, restarting...');
36
+ try {
37
+ // Kill server (ignore errors - it might already be dead)
38
+ await execCommandFull('adb', ['kill-server']);
39
+ // Start server
40
+ await execCommand('adb', ['start-server']);
41
+ console.log('ADB server restarted successfully');
42
+ return true;
43
+ }
44
+ catch (error) {
45
+ console.error('Failed to restart ADB server:', error.message);
46
+ return false;
47
+ }
48
+ }
49
+ /**
50
+ * Check if ADB devices are connected (with auto-recovery for server issues)
51
+ */
52
+ export async function checkADBDevices(retryCount = 0) {
53
+ try {
54
+ const output = await execCommand('adb', ['devices']);
55
+ const lines = output.trim().split('\n').slice(1); // Skip header
56
+ const devices = lines.filter(line => line.trim() && !line.includes('List of devices'));
57
+ if (devices.length === 0) {
58
+ console.error('Error: No ADB devices connected');
59
+ console.error('');
60
+ console.error('Please connect your Quest device via USB and enable USB debugging');
61
+ console.error('');
62
+ process.exit(1);
63
+ }
64
+ console.log(`Found ${devices.length} ADB device(s)`);
65
+ return true;
66
+ }
67
+ catch (error) {
68
+ const errorMsg = error.message;
69
+ // Check if it's a server issue
70
+ const isServerIssue = errorMsg.includes('protocol fault') ||
71
+ errorMsg.includes('Connection reset') ||
72
+ errorMsg.includes('server version') ||
73
+ errorMsg.includes('cannot connect to daemon');
74
+ if (isServerIssue && retryCount === 0) {
75
+ const restarted = await restartADBServer();
76
+ if (restarted) {
77
+ return await checkADBDevices(1);
78
+ }
79
+ }
80
+ console.error('Error: Failed to list ADB devices:', errorMsg);
81
+ console.error('');
82
+ console.error('Try running: adb kill-server && adb start-server');
83
+ console.error('');
84
+ process.exit(1);
85
+ }
86
+ }
87
+ /**
88
+ * Check if a port is already listening on localhost
89
+ */
90
+ export function isPortListening(port) {
91
+ return new Promise((resolve) => {
92
+ const socket = new net.Socket();
93
+ socket.setTimeout(500);
94
+ socket.on('connect', () => {
95
+ socket.destroy();
96
+ resolve(true);
97
+ });
98
+ socket.on('timeout', () => {
99
+ socket.destroy();
100
+ resolve(false);
101
+ });
102
+ socket.on('error', () => {
103
+ resolve(false);
104
+ });
105
+ socket.connect(port, '127.0.0.1');
106
+ });
107
+ }
108
+ /**
109
+ * Idempotently set up ADB port forwarding for a given port
110
+ */
111
+ export async function ensurePortForwarding(port) {
112
+ try {
113
+ // Check reverse forwarding (Quest -> Host for dev server)
114
+ const reverseList = await execCommand('adb', ['reverse', '--list']);
115
+ const reverseExists = reverseList.includes(`tcp:${port}`);
116
+ if (reverseExists) {
117
+ console.log(`ADB reverse port forwarding already set up: Quest:${port} -> Host:${port}`);
118
+ }
119
+ else {
120
+ await execCommand('adb', ['reverse', `tcp:${port}`, `tcp:${port}`]);
121
+ console.log(`ADB reverse port forwarding set up: Quest:${port} -> Host:${port}`);
122
+ }
123
+ // Check forward forwarding (Host -> Quest for CDP)
124
+ const cdpPortListening = await isPortListening(CDP_PORT);
125
+ if (cdpPortListening) {
126
+ console.log(`CDP port ${CDP_PORT} already listening (forwarding assumed active)`);
127
+ }
128
+ else {
129
+ try {
130
+ await execCommand('adb', ['forward', `tcp:${CDP_PORT}`, 'localabstract:chrome_devtools_remote']);
131
+ console.log(`ADB forward port forwarding set up: Host:${CDP_PORT} -> Quest:chrome_devtools_remote (CDP)`);
132
+ }
133
+ catch (forwardError) {
134
+ const errorMsg = forwardError.message;
135
+ if (errorMsg.includes('Address already in use')) {
136
+ console.log(`CDP port ${CDP_PORT} is now active (another process set it up)`);
137
+ }
138
+ else {
139
+ throw forwardError;
140
+ }
141
+ }
142
+ }
143
+ }
144
+ catch (error) {
145
+ console.error('Failed to set up port forwarding:', error.message);
146
+ process.exit(1);
147
+ }
148
+ }
149
+ /**
150
+ * Check if Quest browser is running
151
+ */
152
+ export async function isBrowserRunning() {
153
+ try {
154
+ const result = await execCommandFull('adb', ['shell', 'ps | grep com.oculus.browser']);
155
+ return result.stdout.includes('com.oculus.browser');
156
+ }
157
+ catch (error) {
158
+ return false;
159
+ }
160
+ }
161
+ /**
162
+ * Launch Quest browser with a URL using am start
163
+ */
164
+ export async function launchBrowser(url) {
165
+ console.log('Launching Quest browser...');
166
+ try {
167
+ await execCommand('adb', [
168
+ 'shell',
169
+ 'am',
170
+ 'start',
171
+ '-a',
172
+ 'android.intent.action.VIEW',
173
+ '-d',
174
+ url,
175
+ 'com.oculus.browser'
176
+ ]);
177
+ console.log(`Quest browser launched with URL: ${url}`);
178
+ return true;
179
+ }
180
+ catch (error) {
181
+ console.error('Failed to launch Quest browser:', error.message);
182
+ return false;
183
+ }
184
+ }
185
+ /**
186
+ * Get CDP port
187
+ */
188
+ export function getCDPPort() {
189
+ return CDP_PORT;
190
+ }
191
+ //# sourceMappingURL=adb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adb.js","sourceRoot":"","sources":["../../src/utils/adb.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Shell command execution utilities
3
+ */
4
+ export interface ExecResult {
5
+ stdout: string;
6
+ stderr: string;
7
+ code: number;
8
+ }
9
+ /**
10
+ * Execute a shell command and return a promise with stdout
11
+ */
12
+ export declare function execCommand(command: string, args?: string[]): Promise<string>;
13
+ /**
14
+ * Execute a shell command and return full result (doesn't throw on non-zero exit)
15
+ */
16
+ export declare function execCommandFull(command: string, args?: string[]): Promise<ExecResult>;
17
+ //# sourceMappingURL=exec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../src/utils/exec.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAgCjF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CA8BzF"}