@myerscarpenter/quest-dev 1.0.3 → 1.0.5

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.
@@ -1 +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"}
1
+ {"version":3,"file":"screenshot.d.ts","sourceRoot":"","sources":["../../src/commands/screenshot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA2EH;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwDzE"}
@@ -3,8 +3,8 @@
3
3
  * Triggers Quest's native screenshot service and pulls the file
4
4
  */
5
5
  import { resolve } from 'path';
6
- import { checkADBPath, checkADBDevices } from '../utils/adb.js';
7
- import { execCommand } from '../utils/exec.js';
6
+ import { checkADBPath, checkADBDevices, checkUSBFileTransfer, checkQuestAwake } from '../utils/adb.js';
7
+ import { execCommand, execCommandFull } from '../utils/exec.js';
8
8
  /**
9
9
  * Trigger Quest screenshot service
10
10
  */
@@ -35,12 +35,9 @@ async function getMostRecentScreenshot() {
35
35
  const output = await execCommand('adb', ['shell', 'ls', '-t', '/sdcard/Oculus/Screenshots/']);
36
36
  const files = output.split('\n').filter(line => line.trim() && line.endsWith('.jpg'));
37
37
  if (files.length === 0) {
38
- console.error('No screenshots found in /sdcard/Oculus/Screenshots/');
39
38
  return null;
40
39
  }
41
- const mostRecent = files[0].trim();
42
- console.log(`Found most recent screenshot: ${mostRecent}`);
43
- return mostRecent;
40
+ return files[0].trim();
44
41
  }
45
42
  catch (error) {
46
43
  console.error('Failed to list screenshots:', error.message);
@@ -62,6 +59,19 @@ async function pullScreenshot(filename, outputPath) {
62
59
  return false;
63
60
  }
64
61
  }
62
+ /**
63
+ * Delete screenshot from Quest after pulling
64
+ */
65
+ async function deleteRemoteScreenshot(filename) {
66
+ const remotePath = `/sdcard/Oculus/Screenshots/${filename}`;
67
+ const result = await execCommandFull('adb', ['shell', 'rm', remotePath]);
68
+ if (result.code !== 0) {
69
+ console.warn(`Warning: Failed to delete screenshot from Quest: ${filename}`);
70
+ }
71
+ else {
72
+ console.log(`Deleted screenshot from Quest: ${filename}`);
73
+ }
74
+ }
65
75
  /**
66
76
  * Main screenshot command handler
67
77
  */
@@ -71,22 +81,44 @@ export async function screenshotCommand(outputPath) {
71
81
  // Check prerequisites
72
82
  checkADBPath();
73
83
  await checkADBDevices();
84
+ await checkUSBFileTransfer();
85
+ await checkQuestAwake();
86
+ // Get existing most recent screenshot (to detect if a new one is created)
87
+ const existingScreenshot = await getMostRecentScreenshot();
74
88
  // Trigger screenshot
75
89
  if (!await triggerScreenshot()) {
76
90
  process.exit(1);
77
91
  }
78
- // Wait for screenshot to save
92
+ // Wait for screenshot to save and verify a new one was created
79
93
  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();
94
+ let filename = null;
95
+ const maxAttempts = 10;
96
+ for (let i = 0; i < maxAttempts; i++) {
97
+ await new Promise(resolve => setTimeout(resolve, 500));
98
+ const newScreenshot = await getMostRecentScreenshot();
99
+ if (newScreenshot && newScreenshot !== existingScreenshot) {
100
+ filename = newScreenshot;
101
+ console.log(`New screenshot created: ${filename}`);
102
+ break;
103
+ }
104
+ }
83
105
  if (!filename) {
106
+ console.error('Error: Screenshot was not created');
107
+ console.error('');
108
+ console.error('The screenshot service was triggered but no new screenshot appeared.');
109
+ console.error('This can happen if:');
110
+ console.error('- The Quest is asleep or the screen is off');
111
+ console.error('- The Quest is showing a system dialog');
112
+ console.error('- There is insufficient storage space');
113
+ console.error('');
84
114
  process.exit(1);
85
115
  }
86
116
  // Pull screenshot
87
117
  if (!await pullScreenshot(filename, resolvedPath)) {
88
118
  process.exit(1);
89
119
  }
120
+ // Delete from Quest after successful pull
121
+ await deleteRemoteScreenshot(filename);
90
122
  console.log('\nDone!\n');
91
123
  }
92
124
  //# sourceMappingURL=screenshot.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../../src/commands/screenshot.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../../src/commands/screenshot.ts"],"names":[],"mappings":"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"}
@@ -29,4 +29,14 @@ export declare function launchBrowser(url: string): Promise<boolean>;
29
29
  * Get CDP port
30
30
  */
31
31
  export declare function getCDPPort(): number;
32
+ /**
33
+ * Check if USB file transfer is authorized on Quest
34
+ * After reboot, user must click notification to allow file access
35
+ */
36
+ export declare function checkUSBFileTransfer(): Promise<void>;
37
+ /**
38
+ * Check if Quest display is awake
39
+ * Screenshots cannot be taken when the display is off
40
+ */
41
+ export declare function checkQuestAwake(): Promise<void>;
32
42
  //# sourceMappingURL=adb.d.ts.map
@@ -1 +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"}
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,CA0CtE;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;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAe1D;AAED;;;GAGG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAUrD"}
@@ -121,24 +121,28 @@ export async function ensurePortForwarding(port) {
121
121
  console.log(`ADB reverse port forwarding set up: Quest:${port} -> Host:${port}`);
122
122
  }
123
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)`);
124
+ // First check if ADB already has this forwarding set up
125
+ const forwardList = await execCommand('adb', ['forward', '--list']);
126
+ const forwardExists = forwardList.includes(`tcp:${CDP_PORT}`) && forwardList.includes('chrome_devtools_remote');
127
+ if (forwardExists) {
128
+ console.log(`CDP port ${CDP_PORT} forwarding already set up`);
127
129
  }
128
130
  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
- }
131
+ // Check if something else is using the port
132
+ const cdpPortListening = await isPortListening(CDP_PORT);
133
+ if (cdpPortListening) {
134
+ console.error(`Error: Port ${CDP_PORT} is already in use by another process`);
135
+ console.error('');
136
+ console.error('CDP port forwarding requires port 9223 to be free.');
137
+ console.error('Please stop the process using this port and try again.');
138
+ console.error('');
139
+ console.error('To find what is using the port:');
140
+ console.error(` lsof -i :${CDP_PORT}`);
141
+ console.error('');
142
+ process.exit(1);
141
143
  }
144
+ await execCommand('adb', ['forward', `tcp:${CDP_PORT}`, 'localabstract:chrome_devtools_remote']);
145
+ console.log(`ADB forward port forwarding set up: Host:${CDP_PORT} -> Quest:chrome_devtools_remote (CDP)`);
142
146
  }
143
147
  }
144
148
  catch (error) {
@@ -188,4 +192,37 @@ export async function launchBrowser(url) {
188
192
  export function getCDPPort() {
189
193
  return CDP_PORT;
190
194
  }
195
+ /**
196
+ * Check if USB file transfer is authorized on Quest
197
+ * After reboot, user must click notification to allow file access
198
+ */
199
+ export async function checkUSBFileTransfer() {
200
+ const result = await execCommandFull('adb', ['shell', 'ls', '/sdcard/']);
201
+ if (result.code !== 0 ||
202
+ result.stdout.includes('Permission denied') ||
203
+ result.stderr.includes('Permission denied')) {
204
+ console.error('Error: USB file transfer not authorized on Quest');
205
+ console.error('');
206
+ console.error('After rebooting your Quest, you need to authorize USB file transfers:');
207
+ console.error('1. Put on your Quest headset');
208
+ console.error('2. Look for the "Allow access to data" notification');
209
+ console.error('3. Click "Allow" to authorize file transfers');
210
+ console.error('');
211
+ process.exit(1);
212
+ }
213
+ }
214
+ /**
215
+ * Check if Quest display is awake
216
+ * Screenshots cannot be taken when the display is off
217
+ */
218
+ export async function checkQuestAwake() {
219
+ const result = await execCommandFull('adb', ['shell', 'dumpsys', 'power']);
220
+ if (result.stdout.includes('mWakefulness=Asleep')) {
221
+ console.error('Error: Quest display is off');
222
+ console.error('');
223
+ console.error('Put on the Quest headset or press the power button to wake it.');
224
+ console.error('');
225
+ process.exit(1);
226
+ }
227
+ }
191
228
  //# sourceMappingURL=adb.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"adb.js","sourceRoot":"","sources":["../../src/utils/adb.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"adb.js","sourceRoot":"","sources":["../../src/utils/adb.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myerscarpenter/quest-dev",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "CLI for Meta Quest Browser development - screenshot and URL opening via ADB and cdp-cli",
5
5
  "type": "module",
6
6
  "bin": {
@@ -4,8 +4,8 @@
4
4
  */
5
5
 
6
6
  import { resolve } from 'path';
7
- import { checkADBPath, checkADBDevices } from '../utils/adb.js';
8
- import { execCommand } from '../utils/exec.js';
7
+ import { checkADBPath, checkADBDevices, checkUSBFileTransfer, checkQuestAwake } from '../utils/adb.js';
8
+ import { execCommand, execCommandFull } from '../utils/exec.js';
9
9
 
10
10
  /**
11
11
  * Trigger Quest screenshot service
@@ -38,13 +38,10 @@ async function getMostRecentScreenshot(): Promise<string | null> {
38
38
  const files = output.split('\n').filter(line => line.trim() && line.endsWith('.jpg'));
39
39
 
40
40
  if (files.length === 0) {
41
- console.error('No screenshots found in /sdcard/Oculus/Screenshots/');
42
41
  return null;
43
42
  }
44
43
 
45
- const mostRecent = files[0].trim();
46
- console.log(`Found most recent screenshot: ${mostRecent}`);
47
- return mostRecent;
44
+ return files[0].trim();
48
45
  } catch (error) {
49
46
  console.error('Failed to list screenshots:', (error as Error).message);
50
47
  return null;
@@ -66,6 +63,19 @@ async function pullScreenshot(filename: string, outputPath: string): Promise<boo
66
63
  }
67
64
  }
68
65
 
66
+ /**
67
+ * Delete screenshot from Quest after pulling
68
+ */
69
+ async function deleteRemoteScreenshot(filename: string): Promise<void> {
70
+ const remotePath = `/sdcard/Oculus/Screenshots/${filename}`;
71
+ const result = await execCommandFull('adb', ['shell', 'rm', remotePath]);
72
+ if (result.code !== 0) {
73
+ console.warn(`Warning: Failed to delete screenshot from Quest: ${filename}`);
74
+ } else {
75
+ console.log(`Deleted screenshot from Quest: ${filename}`);
76
+ }
77
+ }
78
+
69
79
  /**
70
80
  * Main screenshot command handler
71
81
  */
@@ -77,19 +87,42 @@ export async function screenshotCommand(outputPath: string): Promise<void> {
77
87
  // Check prerequisites
78
88
  checkADBPath();
79
89
  await checkADBDevices();
90
+ await checkUSBFileTransfer();
91
+ await checkQuestAwake();
92
+
93
+ // Get existing most recent screenshot (to detect if a new one is created)
94
+ const existingScreenshot = await getMostRecentScreenshot();
80
95
 
81
96
  // Trigger screenshot
82
97
  if (!await triggerScreenshot()) {
83
98
  process.exit(1);
84
99
  }
85
100
 
86
- // Wait for screenshot to save
101
+ // Wait for screenshot to save and verify a new one was created
87
102
  console.log('Waiting for screenshot to save...');
88
- await new Promise(resolve => setTimeout(resolve, 2000));
103
+ let filename: string | null = null;
104
+ const maxAttempts = 10;
105
+
106
+ for (let i = 0; i < maxAttempts; i++) {
107
+ await new Promise(resolve => setTimeout(resolve, 500));
108
+ const newScreenshot = await getMostRecentScreenshot();
109
+
110
+ if (newScreenshot && newScreenshot !== existingScreenshot) {
111
+ filename = newScreenshot;
112
+ console.log(`New screenshot created: ${filename}`);
113
+ break;
114
+ }
115
+ }
89
116
 
90
- // Get most recent screenshot
91
- const filename = await getMostRecentScreenshot();
92
117
  if (!filename) {
118
+ console.error('Error: Screenshot was not created');
119
+ console.error('');
120
+ console.error('The screenshot service was triggered but no new screenshot appeared.');
121
+ console.error('This can happen if:');
122
+ console.error('- The Quest is asleep or the screen is off');
123
+ console.error('- The Quest is showing a system dialog');
124
+ console.error('- There is insufficient storage space');
125
+ console.error('');
93
126
  process.exit(1);
94
127
  }
95
128
 
@@ -98,5 +131,8 @@ export async function screenshotCommand(outputPath: string): Promise<void> {
98
131
  process.exit(1);
99
132
  }
100
133
 
134
+ // Delete from Quest after successful pull
135
+ await deleteRemoteScreenshot(filename);
136
+
101
137
  console.log('\nDone!\n');
102
138
  }
package/src/utils/adb.ts CHANGED
@@ -130,22 +130,29 @@ export async function ensurePortForwarding(port: number): Promise<void> {
130
130
  }
131
131
 
132
132
  // Check forward forwarding (Host -> Quest for CDP)
133
- const cdpPortListening = await isPortListening(CDP_PORT);
133
+ // First check if ADB already has this forwarding set up
134
+ const forwardList = await execCommand('adb', ['forward', '--list']);
135
+ const forwardExists = forwardList.includes(`tcp:${CDP_PORT}`) && forwardList.includes('chrome_devtools_remote');
134
136
 
135
- if (cdpPortListening) {
136
- console.log(`CDP port ${CDP_PORT} already listening (forwarding assumed active)`);
137
+ if (forwardExists) {
138
+ console.log(`CDP port ${CDP_PORT} forwarding already set up`);
137
139
  } else {
138
- try {
139
- await execCommand('adb', ['forward', `tcp:${CDP_PORT}`, 'localabstract:chrome_devtools_remote']);
140
- console.log(`ADB forward port forwarding set up: Host:${CDP_PORT} -> Quest:chrome_devtools_remote (CDP)`);
141
- } catch (forwardError) {
142
- const errorMsg = (forwardError as Error).message;
143
- if (errorMsg.includes('Address already in use')) {
144
- console.log(`CDP port ${CDP_PORT} is now active (another process set it up)`);
145
- } else {
146
- throw forwardError;
147
- }
140
+ // Check if something else is using the port
141
+ const cdpPortListening = await isPortListening(CDP_PORT);
142
+ if (cdpPortListening) {
143
+ console.error(`Error: Port ${CDP_PORT} is already in use by another process`);
144
+ console.error('');
145
+ console.error('CDP port forwarding requires port 9223 to be free.');
146
+ console.error('Please stop the process using this port and try again.');
147
+ console.error('');
148
+ console.error('To find what is using the port:');
149
+ console.error(` lsof -i :${CDP_PORT}`);
150
+ console.error('');
151
+ process.exit(1);
148
152
  }
153
+
154
+ await execCommand('adb', ['forward', `tcp:${CDP_PORT}`, 'localabstract:chrome_devtools_remote']);
155
+ console.log(`ADB forward port forwarding set up: Host:${CDP_PORT} -> Quest:chrome_devtools_remote (CDP)`);
149
156
  }
150
157
  } catch (error) {
151
158
  console.error('Failed to set up port forwarding:', (error as Error).message);
@@ -195,3 +202,40 @@ export async function launchBrowser(url: string): Promise<boolean> {
195
202
  export function getCDPPort(): number {
196
203
  return CDP_PORT;
197
204
  }
205
+
206
+ /**
207
+ * Check if USB file transfer is authorized on Quest
208
+ * After reboot, user must click notification to allow file access
209
+ */
210
+ export async function checkUSBFileTransfer(): Promise<void> {
211
+ const result = await execCommandFull('adb', ['shell', 'ls', '/sdcard/']);
212
+
213
+ if (result.code !== 0 ||
214
+ result.stdout.includes('Permission denied') ||
215
+ result.stderr.includes('Permission denied')) {
216
+ console.error('Error: USB file transfer not authorized on Quest');
217
+ console.error('');
218
+ console.error('After rebooting your Quest, you need to authorize USB file transfers:');
219
+ console.error('1. Put on your Quest headset');
220
+ console.error('2. Look for the "Allow access to data" notification');
221
+ console.error('3. Click "Allow" to authorize file transfers');
222
+ console.error('');
223
+ process.exit(1);
224
+ }
225
+ }
226
+
227
+ /**
228
+ * Check if Quest display is awake
229
+ * Screenshots cannot be taken when the display is off
230
+ */
231
+ export async function checkQuestAwake(): Promise<void> {
232
+ const result = await execCommandFull('adb', ['shell', 'dumpsys', 'power']);
233
+
234
+ if (result.stdout.includes('mWakefulness=Asleep')) {
235
+ console.error('Error: Quest display is off');
236
+ console.error('');
237
+ console.error('Put on the Quest headset or press the power button to wake it.');
238
+ console.error('');
239
+ process.exit(1);
240
+ }
241
+ }