source: trip-planner-front/node_modules/open/index.js@ 8d391a1

Last change on this file since 8d391a1 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 6.7 KB
Line 
1const path = require('path');
2const childProcess = require('child_process');
3const {promises: fs, constants: fsConstants} = require('fs');
4const isWsl = require('is-wsl');
5const isDocker = require('is-docker');
6const defineLazyProperty = require('define-lazy-prop');
7
8// Path to included `xdg-open`.
9const localXdgOpenPath = path.join(__dirname, 'xdg-open');
10
11const {platform, arch} = process;
12
13/**
14Get the mount point for fixed drives in WSL.
15
16@inner
17@returns {string} The mount point.
18*/
19const getWslDrivesMountPoint = (() => {
20 // Default value for "root" param
21 // according to https://docs.microsoft.com/en-us/windows/wsl/wsl-config
22 const defaultMountPoint = '/mnt/';
23
24 let mountPoint;
25
26 return async function () {
27 if (mountPoint) {
28 // Return memoized mount point value
29 return mountPoint;
30 }
31
32 const configFilePath = '/etc/wsl.conf';
33
34 let isConfigFileExists = false;
35 try {
36 await fs.access(configFilePath, fsConstants.F_OK);
37 isConfigFileExists = true;
38 } catch {}
39
40 if (!isConfigFileExists) {
41 return defaultMountPoint;
42 }
43
44 const configContent = await fs.readFile(configFilePath, {encoding: 'utf8'});
45 const configMountPoint = /(?<!#.*)root\s*=\s*(?<mountPoint>.*)/g.exec(configContent);
46
47 if (!configMountPoint) {
48 return defaultMountPoint;
49 }
50
51 mountPoint = configMountPoint.groups.mountPoint.trim();
52 mountPoint = mountPoint.endsWith('/') ? mountPoint : `${mountPoint}/`;
53
54 return mountPoint;
55 };
56})();
57
58const pTryEach = async (array, mapper) => {
59 let latestError;
60
61 for (const item of array) {
62 try {
63 return await mapper(item); // eslint-disable-line no-await-in-loop
64 } catch (error) {
65 latestError = error;
66 }
67 }
68
69 throw latestError;
70};
71
72const open = async (target, options) => {
73 if (typeof target !== 'string') {
74 throw new TypeError('Expected a `target`');
75 }
76
77 options = {
78 wait: false,
79 background: false,
80 newInstance: false,
81 allowNonzeroExitCode: false,
82 ...options
83 };
84
85 if (Array.isArray(options.app)) {
86 return pTryEach(options.app, singleApp => open(target, {
87 ...options,
88 app: singleApp
89 }));
90 }
91
92 let {name: app, arguments: appArguments = []} = options.app || {};
93 appArguments = [...appArguments];
94
95 if (Array.isArray(app)) {
96 return pTryEach(app, appName => open(target, {
97 ...options,
98 app: {
99 name: appName,
100 arguments: appArguments
101 }
102 }));
103 }
104
105 let command;
106 const cliArguments = [];
107 const childProcessOptions = {};
108
109 if (platform === 'darwin') {
110 command = 'open';
111
112 if (options.wait) {
113 cliArguments.push('--wait-apps');
114 }
115
116 if (options.background) {
117 cliArguments.push('--background');
118 }
119
120 if (options.newInstance) {
121 cliArguments.push('--new');
122 }
123
124 if (app) {
125 cliArguments.push('-a', app);
126 }
127 } else if (platform === 'win32' || (isWsl && !isDocker())) {
128 const mountPoint = await getWslDrivesMountPoint();
129
130 command = isWsl ?
131 `${mountPoint}c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe` :
132 `${process.env.SYSTEMROOT}\\System32\\WindowsPowerShell\\v1.0\\powershell`;
133
134 cliArguments.push(
135 '-NoProfile',
136 '-NonInteractive',
137 '–ExecutionPolicy',
138 'Bypass',
139 '-EncodedCommand'
140 );
141
142 if (!isWsl) {
143 childProcessOptions.windowsVerbatimArguments = true;
144 }
145
146 const encodedArguments = ['Start'];
147
148 if (options.wait) {
149 encodedArguments.push('-Wait');
150 }
151
152 if (app) {
153 // Double quote with double quotes to ensure the inner quotes are passed through.
154 // Inner quotes are delimited for PowerShell interpretation with backticks.
155 encodedArguments.push(`"\`"${app}\`""`, '-ArgumentList');
156 appArguments.unshift(target);
157 } else {
158 encodedArguments.push(`"${target}"`);
159 }
160
161 if (appArguments.length > 0) {
162 appArguments = appArguments.map(arg => `"\`"${arg}\`""`);
163 encodedArguments.push(appArguments.join(','));
164 }
165
166 // Using Base64-encoded command, accepted by PowerShell, to allow special characters.
167 target = Buffer.from(encodedArguments.join(' '), 'utf16le').toString('base64');
168 } else {
169 if (app) {
170 command = app;
171 } else {
172 // When bundled by Webpack, there's no actual package file path and no local `xdg-open`.
173 const isBundled = !__dirname || __dirname === '/';
174
175 // Check if local `xdg-open` exists and is executable.
176 let exeLocalXdgOpen = false;
177 try {
178 await fs.access(localXdgOpenPath, fsConstants.X_OK);
179 exeLocalXdgOpen = true;
180 } catch {}
181
182 const useSystemXdgOpen = process.versions.electron ||
183 platform === 'android' || isBundled || !exeLocalXdgOpen;
184 command = useSystemXdgOpen ? 'xdg-open' : localXdgOpenPath;
185 }
186
187 if (appArguments.length > 0) {
188 cliArguments.push(...appArguments);
189 }
190
191 if (!options.wait) {
192 // `xdg-open` will block the process unless stdio is ignored
193 // and it's detached from the parent even if it's unref'd.
194 childProcessOptions.stdio = 'ignore';
195 childProcessOptions.detached = true;
196 }
197 }
198
199 cliArguments.push(target);
200
201 if (platform === 'darwin' && appArguments.length > 0) {
202 cliArguments.push('--args', ...appArguments);
203 }
204
205 const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
206
207 if (options.wait) {
208 return new Promise((resolve, reject) => {
209 subprocess.once('error', reject);
210
211 subprocess.once('close', exitCode => {
212 if (options.allowNonzeroExitCode && exitCode > 0) {
213 reject(new Error(`Exited with code ${exitCode}`));
214 return;
215 }
216
217 resolve(subprocess);
218 });
219 });
220 }
221
222 subprocess.unref();
223
224 return subprocess;
225};
226
227function detectArchBinary(binary) {
228 if (typeof binary === 'string' || Array.isArray(binary)) {
229 return binary;
230 }
231
232 const {[arch]: archBinary} = binary;
233
234 if (!archBinary) {
235 throw new Error(`${arch} is not supported`);
236 }
237
238 return archBinary;
239}
240
241function detectPlatformBinary({[platform]: platformBinary}, {wsl}) {
242 if (wsl && isWsl) {
243 return detectArchBinary(wsl);
244 }
245
246 if (!platformBinary) {
247 throw new Error(`${platform} is not supported`);
248 }
249
250 return detectArchBinary(platformBinary);
251}
252
253const apps = {};
254
255defineLazyProperty(apps, 'chrome', () => detectPlatformBinary({
256 darwin: 'google chrome',
257 win32: 'chrome',
258 linux: ['google-chrome', 'google-chrome-stable']
259}, {
260 wsl: {
261 ia32: '/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe',
262 x64: ['/mnt/c/Program Files/Google/Chrome/Application/chrome.exe', '/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe']
263 }
264}));
265
266defineLazyProperty(apps, 'firefox', () => detectPlatformBinary({
267 darwin: 'firefox',
268 win32: 'C:\\Program Files\\Mozilla Firefox\\firefox.exe',
269 linux: 'firefox'
270}, {
271 wsl: '/mnt/c/Program Files/Mozilla Firefox/firefox.exe'
272}));
273
274defineLazyProperty(apps, 'edge', () => detectPlatformBinary({
275 darwin: 'microsoft edge',
276 win32: 'msedge',
277 linux: 'microsoft-edge'
278}, {
279 wsl: '/mnt/c/Program Files (x86)/Microsoft/Edge/Application/msedge.exe'
280}));
281
282open.apps = apps;
283
284module.exports = open;
Note: See TracBrowser for help on using the repository browser.