UNPKG

3.71 kBJavaScriptView Raw
1// Sourced from Snowpack
2// https://github.com/snowpackjs/snowpack/blob/2cbbdbbad1c4f842f86ff56d19f86afedf07d2e2/snowpack/src/util.ts#L156:L227
3/*
4 * MIT License
5 *
6 * Copyright (c) 2019 Fred K. Schott
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in all
16 * copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 */
26import open from "open";
27import execa from "execa";
28import { join } from "path";
29const cwd = process.cwd();
30const appNames = {
31 win32: {
32 brave: "brave",
33 chrome: "chrome",
34 },
35 darwin: {
36 brave: "Brave Browser",
37 chrome: "Google Chrome",
38 },
39 linux: {
40 brave: "brave",
41 chrome: "google-chrome",
42 },
43};
44async function openInExistingChromeBrowser(url) {
45 // see if Chrome process is open; fail if not
46 await execa.command('ps cax | grep "Google Chrome"', {
47 shell: true,
48 });
49 // use open Chrome tab if exists; create new Chrome tab if not
50 const openChrome = execa(`osascript ${join("node_modules", "microsite", "assets", "openChrome.appleScript")} "${encodeURI(url)}"`, {
51 cwd,
52 stdio: "ignore",
53 shell: true,
54 });
55 // if Chrome doesn’t respond within 3s, fall back to opening new tab in default browser
56 let isChromeStalled = setTimeout(() => {
57 openChrome.cancel();
58 }, 3000);
59 try {
60 await openChrome;
61 }
62 catch (err) {
63 console.error(err);
64 if (err.isCanceled) {
65 console.warn(`Chrome not responding to Snowpack after 3s. Opening in new tab.`);
66 }
67 else {
68 console.error(err.toString() || err);
69 }
70 throw err;
71 }
72 finally {
73 clearTimeout(isChromeStalled);
74 }
75}
76export async function openInBrowser(protocol, hostname, port, basePath, browser) {
77 const url = `${protocol}//${hostname}:${port}${basePath.replace(/\/$/, '')}`;
78 browser = /chrome/i.test(browser)
79 ? appNames[process.platform]["chrome"]
80 : /brave/i.test(browser)
81 ? appNames[process.platform]["brave"]
82 : browser;
83 const isMac = process.platform === "darwin";
84 const isBrowserChrome = /chrome|default/i.test(browser);
85 if (!isMac || !isBrowserChrome) {
86 await (browser === "default" ? open(url) : open(url, { app: browser }));
87 return;
88 }
89 try {
90 // If we're on macOS, and we haven't requested a specific browser,
91 // we can try opening Chrome with AppleScript. This lets us reuse an
92 // existing tab when possible instead of creating a new one.
93 await openInExistingChromeBrowser(url);
94 }
95 catch (err) {
96 // if no open Chrome process, just go ahead and open default browser.
97 await open(url);
98 }
99}