source dump of claude code
at main 68 lines 1.9 kB view raw
1import { execFileNoThrow } from './execFileNoThrow.js' 2 3function validateUrl(url: string): void { 4 let parsedUrl: URL 5 6 try { 7 parsedUrl = new URL(url) 8 } catch (_error) { 9 throw new Error(`Invalid URL format: ${url}`) 10 } 11 12 // Validate URL protocol for security 13 if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') { 14 throw new Error( 15 `Invalid URL protocol: must use http:// or https://, got ${parsedUrl.protocol}`, 16 ) 17 } 18} 19 20/** 21 * Open a file or folder path using the system's default handler. 22 * Uses `open` on macOS, `explorer` on Windows, `xdg-open` on Linux. 23 */ 24export async function openPath(path: string): Promise<boolean> { 25 try { 26 const platform = process.platform 27 if (platform === 'win32') { 28 const { code } = await execFileNoThrow('explorer', [path]) 29 return code === 0 30 } 31 const command = platform === 'darwin' ? 'open' : 'xdg-open' 32 const { code } = await execFileNoThrow(command, [path]) 33 return code === 0 34 } catch (_) { 35 return false 36 } 37} 38 39export async function openBrowser(url: string): Promise<boolean> { 40 try { 41 // Parse and validate the URL 42 validateUrl(url) 43 44 const browserEnv = process.env.BROWSER 45 const platform = process.platform 46 47 if (platform === 'win32') { 48 if (browserEnv) { 49 // browsers require shell, else they will treat this as a file:/// handle 50 const { code } = await execFileNoThrow(browserEnv, [`"${url}"`]) 51 return code === 0 52 } 53 const { code } = await execFileNoThrow( 54 'rundll32', 55 ['url,OpenURL', url], 56 {}, 57 ) 58 return code === 0 59 } else { 60 const command = 61 browserEnv || (platform === 'darwin' ? 'open' : 'xdg-open') 62 const { code } = await execFileNoThrow(command, [url]) 63 return code === 0 64 } 65 } catch (_) { 66 return false 67 } 68}