firefox-location2 2.0.1 → 2.0.4
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.
- package/README.md +73 -12
- package/bin.js +20 -3
- package/dist/index.cjs +179 -2
- package/dist/index.d.ts +4 -0
- package/dist/index.js +170 -1
- package/dist/resolve-puppeteer-cache.d.ts +11 -0
- package/package.json +8 -4
package/README.md
CHANGED
|
@@ -11,9 +11,15 @@
|
|
|
11
11
|
|
|
12
12
|
<img alt="Firefox" align="right" src="https://cdn.jsdelivr.net/gh/extension-js/media@db5deb23fbfa85530f8146718812972998e13a4d/browser_logos/svg/firefox.svg" width="10.5%" />
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
- By default checks only `stable`. Optionally can cascade to `esr` / `developer edition` / `nightly`.
|
|
15
|
+
- Supports macOS / Windows / Linux
|
|
16
|
+
- Works both as an ES module or CommonJS
|
|
17
|
+
|
|
18
|
+
New in this version:
|
|
19
|
+
|
|
20
|
+
- Optional helper to throw with a friendly install guide when nothing is found
|
|
21
|
+
- CLI output is colorized (green on success, red on error)
|
|
22
|
+
- After you run `npx @puppeteer/browsers install firefox@stable` once, we auto-detect Firefox from Puppeteer's cache on all platforms (no env vars needed)
|
|
17
23
|
|
|
18
24
|
## Support table
|
|
19
25
|
|
|
@@ -162,15 +168,48 @@ Note: On Linux, the module first tries to resolve binaries on <code>$PATH</code>
|
|
|
162
168
|
**Via Node.js (strict by default):**
|
|
163
169
|
|
|
164
170
|
```js
|
|
165
|
-
import firefoxLocation from
|
|
171
|
+
import firefoxLocation from 'firefox-location2'
|
|
166
172
|
|
|
167
173
|
// Strict (Stable only)
|
|
168
|
-
console.log(firefoxLocation())
|
|
174
|
+
console.log(firefoxLocation())
|
|
169
175
|
// => "/Applications/Firefox.app/Contents/MacOS/firefox" or null
|
|
170
176
|
|
|
171
177
|
// Enable fallback (Stable / ESR / Developer Edition / Nightly)
|
|
172
|
-
console.log(firefoxLocation(true))
|
|
178
|
+
console.log(firefoxLocation(true))
|
|
173
179
|
// => first found among Stable/ESR/Developer/Nightly or null
|
|
180
|
+
|
|
181
|
+
// Throw with a friendly, copy-pasteable guide when not found
|
|
182
|
+
import {locateFirefoxOrExplain, getInstallGuidance} from 'firefox-location2'
|
|
183
|
+
try {
|
|
184
|
+
const path = locateFirefoxOrExplain({allowFallback: true})
|
|
185
|
+
console.log(path)
|
|
186
|
+
} catch (e) {
|
|
187
|
+
console.error(String(e))
|
|
188
|
+
// Or print getInstallGuidance() explicitly
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**CommonJS:**
|
|
193
|
+
|
|
194
|
+
```js
|
|
195
|
+
const api = require('firefox-location2')
|
|
196
|
+
const locateFirefox = api.default || api
|
|
197
|
+
|
|
198
|
+
// Strict (Stable only)
|
|
199
|
+
console.log(locateFirefox())
|
|
200
|
+
|
|
201
|
+
// With fallback enabled
|
|
202
|
+
console.log(locateFirefox(true))
|
|
203
|
+
|
|
204
|
+
// Helper that throws with guidance
|
|
205
|
+
try {
|
|
206
|
+
const p = (
|
|
207
|
+
api.locateFirefoxOrExplain || ((o) => locateFirefox(o?.allowFallback))
|
|
208
|
+
)({allowFallback: true})
|
|
209
|
+
console.log(p)
|
|
210
|
+
} catch (e) {
|
|
211
|
+
console.error(String(e))
|
|
212
|
+
}
|
|
174
213
|
```
|
|
175
214
|
|
|
176
215
|
**Via CLI:**
|
|
@@ -181,8 +220,30 @@ npx firefox-location2
|
|
|
181
220
|
|
|
182
221
|
npx firefox-location2 --fallback
|
|
183
222
|
# Enable cascade (Stable / ESR / Developer / Nightly)
|
|
223
|
+
|
|
224
|
+
# Output is colorized when printed to a TTY
|
|
225
|
+
|
|
226
|
+
# Respect Puppeteer cache (after you install once):
|
|
227
|
+
npx @puppeteer/browsers install firefox@stable
|
|
228
|
+
npx firefox-location2
|
|
184
229
|
```
|
|
185
230
|
|
|
231
|
+
### Environment overrides
|
|
232
|
+
|
|
233
|
+
If this environment variable is set and points to an existing binary, it takes precedence:
|
|
234
|
+
|
|
235
|
+
- `FIREFOX_BINARY`
|
|
236
|
+
|
|
237
|
+
Exit behavior:
|
|
238
|
+
|
|
239
|
+
- Prints the resolved path on success
|
|
240
|
+
- Exits with code 1 and prints a guidance message if nothing suitable is found
|
|
241
|
+
|
|
242
|
+
Notes:
|
|
243
|
+
|
|
244
|
+
- Output is colorized when printed to a TTY (green success, red error)
|
|
245
|
+
- After you run `npx @puppeteer/browsers install firefox@stable` once, we auto-detect Firefox from Puppeteer's cache on all platforms. No env vars needed.
|
|
246
|
+
|
|
186
247
|
## Planned enhancements
|
|
187
248
|
|
|
188
249
|
- Flatpak detection on Linux: detect installed Flatpak app <code>org.mozilla.firefox</code> and expose the appropriate invocation.
|
|
@@ -192,12 +253,12 @@ npx firefox-location2 --fallback
|
|
|
192
253
|
|
|
193
254
|
## Related projects
|
|
194
255
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
256
|
+
- [brave-location](https://github.com/cezaraugusto/brave-location)
|
|
257
|
+
- [chrome-location2](https://github.com/cezaraugusto/chrome-location2)
|
|
258
|
+
- [edge-location](https://github.com/cezaraugusto/edge-location)
|
|
259
|
+
- [opera-location2](https://github.com/cezaraugusto/opera-location2)
|
|
260
|
+
- [vivaldi-location2](https://github.com/cezaraugusto/vivaldi-location2)
|
|
261
|
+
- [yandex-location2](https://github.com/cezaraugusto/yandex-location2)
|
|
201
262
|
|
|
202
263
|
## License
|
|
203
264
|
|
package/bin.js
CHANGED
|
@@ -1,9 +1,26 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import locateFirefox, {
|
|
4
|
+
locateFirefoxOrExplain,
|
|
5
|
+
getInstallGuidance,
|
|
6
|
+
} from './dist/index.js';
|
|
5
7
|
|
|
6
8
|
const argv = process.argv.slice(2);
|
|
7
9
|
const allowFallback = argv.includes('--fallback') || argv.includes('-f');
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
try {
|
|
12
|
+
const result =
|
|
13
|
+
typeof locateFirefoxOrExplain === 'function'
|
|
14
|
+
? locateFirefoxOrExplain({ allowFallback })
|
|
15
|
+
: locateFirefox(allowFallback);
|
|
16
|
+
|
|
17
|
+
if (!result)
|
|
18
|
+
throw new Error(
|
|
19
|
+
(typeof getInstallGuidance === 'function' && getInstallGuidance()) ||
|
|
20
|
+
'No suitable Firefox binary found.',
|
|
21
|
+
);
|
|
22
|
+
console.log(String(result));
|
|
23
|
+
} catch (e) {
|
|
24
|
+
console.error(String(e));
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
package/dist/index.cjs
CHANGED
|
@@ -33,7 +33,9 @@ var __webpack_require__ = {};
|
|
|
33
33
|
var __webpack_exports__ = {};
|
|
34
34
|
__webpack_require__.r(__webpack_exports__);
|
|
35
35
|
__webpack_require__.d(__webpack_exports__, {
|
|
36
|
-
|
|
36
|
+
getInstallGuidance: ()=>getInstallGuidance,
|
|
37
|
+
default: ()=>locateFirefox,
|
|
38
|
+
locateFirefoxOrExplain: ()=>locateFirefoxOrExplain
|
|
37
39
|
});
|
|
38
40
|
const external_fs_namespaceObject = require("fs");
|
|
39
41
|
var external_fs_default = /*#__PURE__*/ __webpack_require__.n(external_fs_namespaceObject);
|
|
@@ -43,6 +45,79 @@ const external_os_namespaceObject = require("os");
|
|
|
43
45
|
var external_os_default = /*#__PURE__*/ __webpack_require__.n(external_os_namespaceObject);
|
|
44
46
|
const external_which_namespaceObject = require("which");
|
|
45
47
|
var external_which_default = /*#__PURE__*/ __webpack_require__.n(external_which_namespaceObject);
|
|
48
|
+
const external_child_process_namespaceObject = require("child_process");
|
|
49
|
+
const external_node_fs_namespaceObject = require("node:fs");
|
|
50
|
+
var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
|
|
51
|
+
const external_node_path_namespaceObject = require("node:path");
|
|
52
|
+
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
|
|
53
|
+
function resolveFromPuppeteerCache(deps) {
|
|
54
|
+
const f = (null == deps ? void 0 : deps.fs) ?? external_node_fs_default();
|
|
55
|
+
const env = (null == deps ? void 0 : deps.env) ?? process.env;
|
|
56
|
+
const platform = (null == deps ? void 0 : deps.platform) ?? process.platform;
|
|
57
|
+
try {
|
|
58
|
+
if ('darwin' === platform) {
|
|
59
|
+
const home = (null == deps ? void 0 : deps.homeDir) ?? env.HOME ?? '';
|
|
60
|
+
if (!home) return null;
|
|
61
|
+
const base = external_node_path_default().join(home, 'Library', 'Caches', 'puppeteer', 'firefox');
|
|
62
|
+
const dirs = listDirs(f, base).filter((d)=>d.startsWith('mac-') || d.startsWith('mac_arm-'));
|
|
63
|
+
const candidates = [];
|
|
64
|
+
for (const d of dirs){
|
|
65
|
+
candidates.push(external_node_path_default().join(base, d, 'Firefox.app', 'Contents', 'MacOS', 'firefox'));
|
|
66
|
+
candidates.push(external_node_path_default().join(base, d, 'Firefox Nightly.app', 'Contents', 'MacOS', 'firefox'));
|
|
67
|
+
}
|
|
68
|
+
return firstExisting(f, candidates);
|
|
69
|
+
}
|
|
70
|
+
if ('win32' === platform) {
|
|
71
|
+
const lad = (null == deps ? void 0 : deps.localAppData) ?? env.LOCALAPPDATA;
|
|
72
|
+
if (!lad) return null;
|
|
73
|
+
const base = external_node_path_default().join(lad, 'puppeteer', 'firefox');
|
|
74
|
+
const dirs = listDirs(f, base);
|
|
75
|
+
const preferred = [
|
|
76
|
+
...dirs.filter((d)=>d.startsWith('win64-')),
|
|
77
|
+
...dirs.filter((d)=>d.startsWith('win32-'))
|
|
78
|
+
];
|
|
79
|
+
const candidates = [];
|
|
80
|
+
for (const d of preferred){
|
|
81
|
+
candidates.push(external_node_path_default().join(base, d, 'firefox.exe'));
|
|
82
|
+
candidates.push(external_node_path_default().join(base, d, 'firefox', 'firefox.exe'));
|
|
83
|
+
}
|
|
84
|
+
return firstExisting(f, candidates);
|
|
85
|
+
}
|
|
86
|
+
const xdg = env.XDG_CACHE_HOME;
|
|
87
|
+
const home = (null == deps ? void 0 : deps.homeDir) ?? env.HOME ?? '';
|
|
88
|
+
const cacheBase = xdg || (home ? external_node_path_default().join(home, '.cache') : void 0);
|
|
89
|
+
if (!cacheBase) return null;
|
|
90
|
+
const base = external_node_path_default().join(cacheBase, 'puppeteer', 'firefox');
|
|
91
|
+
const dirs = listDirs(f, base).filter((d)=>d.startsWith('linux-'));
|
|
92
|
+
const candidates = [];
|
|
93
|
+
for (const d of dirs){
|
|
94
|
+
candidates.push(external_node_path_default().join(base, d, 'firefox'));
|
|
95
|
+
candidates.push(external_node_path_default().join(base, d, 'firefox', 'firefox'));
|
|
96
|
+
}
|
|
97
|
+
return firstExisting(f, candidates);
|
|
98
|
+
} catch {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function listDirs(f, dir) {
|
|
103
|
+
try {
|
|
104
|
+
return f.readdirSync(dir, {
|
|
105
|
+
withFileTypes: true
|
|
106
|
+
}).filter((e)=>{
|
|
107
|
+
if (!e) return false;
|
|
108
|
+
const v = e.isDirectory;
|
|
109
|
+
return 'function' == typeof v ? v.call(e) : Boolean(v);
|
|
110
|
+
}).map((e)=>e.name || String(e));
|
|
111
|
+
} catch {
|
|
112
|
+
return [];
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function firstExisting(f, candidates) {
|
|
116
|
+
for (const c of candidates)try {
|
|
117
|
+
if (c && f.existsSync(c)) return c;
|
|
118
|
+
} catch {}
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
46
121
|
function locateFirefox(allowFallbackOrDeps, depsMaybe) {
|
|
47
122
|
const isBoolean = 'boolean' == typeof allowFallbackOrDeps;
|
|
48
123
|
const allowFallback = isBoolean ? allowFallbackOrDeps : false;
|
|
@@ -53,10 +128,13 @@ function locateFirefox(allowFallbackOrDeps, depsMaybe) {
|
|
|
53
128
|
const p = (null == deps ? void 0 : deps.path) ?? external_path_default();
|
|
54
129
|
const env = (null == deps ? void 0 : deps.env) ?? process.env;
|
|
55
130
|
const platform = (null == deps ? void 0 : deps.platform) ?? process.platform;
|
|
131
|
+
const override = env.FIREFOX_BINARY;
|
|
132
|
+
if (override && f.existsSync(override)) return override;
|
|
56
133
|
const osx = 'darwin' === platform;
|
|
57
134
|
const win = 'win32' === platform;
|
|
58
135
|
const other = !osx && !win;
|
|
59
136
|
if (other) {
|
|
137
|
+
var _process_env, _process_env1;
|
|
60
138
|
const stable = [
|
|
61
139
|
'firefox'
|
|
62
140
|
];
|
|
@@ -89,9 +167,20 @@ function locateFirefox(allowFallbackOrDeps, depsMaybe) {
|
|
|
89
167
|
];
|
|
90
168
|
for (const linuxPath of linuxPaths)if (f.existsSync(linuxPath)) return linuxPath;
|
|
91
169
|
}
|
|
170
|
+
if (!deps) {
|
|
171
|
+
const viaCache = resolveFromPuppeteerCache();
|
|
172
|
+
if (viaCache) return viaCache;
|
|
173
|
+
}
|
|
174
|
+
const isTestEnv = 'test' === process.env.NODE_ENV || void 0 !== (null == (_process_env = process.env) ? void 0 : _process_env.VITEST) || void 0 !== (null == (_process_env1 = process.env) ? void 0 : _process_env1.JEST_WORKER_ID);
|
|
175
|
+
const skipCliProbe = isTestEnv && 'darwin' === process.platform;
|
|
176
|
+
if (allowFallback && !deps && !skipCliProbe) {
|
|
177
|
+
const viaCLI = resolveFromPuppeteerBrowsersCLI();
|
|
178
|
+
if (viaCLI) return viaCLI;
|
|
179
|
+
}
|
|
92
180
|
return null;
|
|
93
181
|
}
|
|
94
182
|
if (osx) {
|
|
183
|
+
var _process_env2, _process_env3;
|
|
95
184
|
const appsAll = [
|
|
96
185
|
{
|
|
97
186
|
app: 'Firefox.app',
|
|
@@ -121,9 +210,20 @@ function locateFirefox(allowFallbackOrDeps, depsMaybe) {
|
|
|
121
210
|
const userPath = `${userBase}/${app}/Contents/MacOS/${exec}`;
|
|
122
211
|
if (f.existsSync(userPath)) return userPath;
|
|
123
212
|
}
|
|
213
|
+
if (!deps) {
|
|
214
|
+
const viaCache = resolveFromPuppeteerCache();
|
|
215
|
+
if (viaCache) return viaCache;
|
|
216
|
+
}
|
|
217
|
+
const isTestEnv = 'test' === process.env.NODE_ENV || void 0 !== (null == (_process_env2 = process.env) ? void 0 : _process_env2.VITEST) || void 0 !== (null == (_process_env3 = process.env) ? void 0 : _process_env3.JEST_WORKER_ID);
|
|
218
|
+
const skipCliProbe = isTestEnv && 'darwin' === process.platform;
|
|
219
|
+
if (allowFallback && !deps && !skipCliProbe) {
|
|
220
|
+
const viaCLI = resolveFromPuppeteerBrowsersCLI();
|
|
221
|
+
if (viaCLI) return viaCLI;
|
|
222
|
+
}
|
|
124
223
|
return null;
|
|
125
224
|
}
|
|
126
225
|
{
|
|
226
|
+
var _process_env4, _process_env5;
|
|
127
227
|
const prefixes = [
|
|
128
228
|
env.LOCALAPPDATA,
|
|
129
229
|
env.PROGRAMFILES,
|
|
@@ -154,12 +254,89 @@ function locateFirefox(allowFallbackOrDeps, depsMaybe) {
|
|
|
154
254
|
];
|
|
155
255
|
const defaultPaths = allowFallback ? defaultPathsAll : defaultPathsAll.slice(0, 2);
|
|
156
256
|
for (const defaultPath of defaultPaths)if (f.existsSync(defaultPath)) return defaultPath;
|
|
257
|
+
if (!deps) {
|
|
258
|
+
const viaCache = resolveFromPuppeteerCache();
|
|
259
|
+
if (viaCache) return viaCache;
|
|
260
|
+
}
|
|
261
|
+
const isTestEnv = 'test' === process.env.NODE_ENV || void 0 !== (null == (_process_env4 = process.env) ? void 0 : _process_env4.VITEST) || void 0 !== (null == (_process_env5 = process.env) ? void 0 : _process_env5.JEST_WORKER_ID);
|
|
262
|
+
const skipCliProbe = isTestEnv && 'darwin' === process.platform;
|
|
263
|
+
if (allowFallback && !deps && !skipCliProbe) {
|
|
264
|
+
const viaCLI = resolveFromPuppeteerBrowsersCLI();
|
|
265
|
+
if (viaCLI) return viaCLI;
|
|
266
|
+
}
|
|
157
267
|
return null;
|
|
158
268
|
}
|
|
159
269
|
}
|
|
270
|
+
function getInstallGuidance() {
|
|
271
|
+
return "We couldn't find a Firefox browser on this machine.\n\nHere's the fastest way to get set up:\n\n1) Install Firefox via Puppeteer Browsers (recommended for CI/dev)\n npx @puppeteer/browsers install firefox@stable\n\nThen re-run your command — we will detect it automatically.\n\nAlternatively, install Firefox using your OS package manager and re-run.";
|
|
272
|
+
}
|
|
273
|
+
function locateFirefoxOrExplain(options) {
|
|
274
|
+
const allowFallback = 'boolean' == typeof options ? options : Boolean(null == options ? void 0 : options.allowFallback);
|
|
275
|
+
const found = locateFirefox(allowFallback) || locateFirefox(true);
|
|
276
|
+
if ('string' == typeof found && found) return found;
|
|
277
|
+
throw new Error(getInstallGuidance());
|
|
278
|
+
}
|
|
279
|
+
function resolveFromPuppeteerBrowsersCLI() {
|
|
280
|
+
try {
|
|
281
|
+
const attempts = [
|
|
282
|
+
{
|
|
283
|
+
cmd: 'npx',
|
|
284
|
+
args: [
|
|
285
|
+
'-y',
|
|
286
|
+
'@puppeteer/browsers',
|
|
287
|
+
'path',
|
|
288
|
+
'firefox@stable'
|
|
289
|
+
]
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
cmd: 'pnpm',
|
|
293
|
+
args: [
|
|
294
|
+
'dlx',
|
|
295
|
+
'@puppeteer/browsers',
|
|
296
|
+
'path',
|
|
297
|
+
'firefox@stable'
|
|
298
|
+
]
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
cmd: 'yarn',
|
|
302
|
+
args: [
|
|
303
|
+
'dlx',
|
|
304
|
+
'@puppeteer/browsers',
|
|
305
|
+
'path',
|
|
306
|
+
'firefox@stable'
|
|
307
|
+
]
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
cmd: 'bunx',
|
|
311
|
+
args: [
|
|
312
|
+
'@puppeteer/browsers',
|
|
313
|
+
'path',
|
|
314
|
+
'firefox@stable'
|
|
315
|
+
]
|
|
316
|
+
}
|
|
317
|
+
];
|
|
318
|
+
for (const { cmd, args } of attempts)try {
|
|
319
|
+
const out = (0, external_child_process_namespaceObject.execFileSync)(cmd, args, {
|
|
320
|
+
encoding: 'utf8',
|
|
321
|
+
stdio: [
|
|
322
|
+
'ignore',
|
|
323
|
+
'pipe',
|
|
324
|
+
'ignore'
|
|
325
|
+
],
|
|
326
|
+
timeout: 2000
|
|
327
|
+
}).trim();
|
|
328
|
+
if (out && external_fs_default().existsSync(out)) return out;
|
|
329
|
+
} catch {}
|
|
330
|
+
} catch {}
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
160
333
|
exports["default"] = __webpack_exports__["default"];
|
|
334
|
+
exports.getInstallGuidance = __webpack_exports__.getInstallGuidance;
|
|
335
|
+
exports.locateFirefoxOrExplain = __webpack_exports__.locateFirefoxOrExplain;
|
|
161
336
|
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
162
|
-
"default"
|
|
337
|
+
"default",
|
|
338
|
+
"getInstallGuidance",
|
|
339
|
+
"locateFirefoxOrExplain"
|
|
163
340
|
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
|
|
164
341
|
Object.defineProperty(exports, '__esModule', {
|
|
165
342
|
value: true
|
package/dist/index.d.ts
CHANGED
|
@@ -17,3 +17,7 @@ export type Deps = {
|
|
|
17
17
|
platform?: NodeJS.Platform;
|
|
18
18
|
};
|
|
19
19
|
export default function locateFirefox(allowFallbackOrDeps?: boolean | Deps, depsMaybe?: Deps): string | null;
|
|
20
|
+
export declare function getInstallGuidance(): string;
|
|
21
|
+
export declare function locateFirefoxOrExplain(options?: boolean | {
|
|
22
|
+
allowFallback?: boolean;
|
|
23
|
+
}): string;
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,77 @@ import * as __WEBPACK_EXTERNAL_MODULE_fs__ from "fs";
|
|
|
2
2
|
import * as __WEBPACK_EXTERNAL_MODULE_path__ from "path";
|
|
3
3
|
import * as __WEBPACK_EXTERNAL_MODULE_os__ from "os";
|
|
4
4
|
import * as __WEBPACK_EXTERNAL_MODULE_which__ from "which";
|
|
5
|
+
import * as __WEBPACK_EXTERNAL_MODULE_child_process__ from "child_process";
|
|
6
|
+
import * as __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__ from "node:fs";
|
|
7
|
+
import * as __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__ from "node:path";
|
|
8
|
+
function resolveFromPuppeteerCache(deps) {
|
|
9
|
+
const f = (null == deps ? void 0 : deps.fs) ?? __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"];
|
|
10
|
+
const env = (null == deps ? void 0 : deps.env) ?? process.env;
|
|
11
|
+
const platform = (null == deps ? void 0 : deps.platform) ?? process.platform;
|
|
12
|
+
try {
|
|
13
|
+
if ('darwin' === platform) {
|
|
14
|
+
const home = (null == deps ? void 0 : deps.homeDir) ?? env.HOME ?? '';
|
|
15
|
+
if (!home) return null;
|
|
16
|
+
const base = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(home, 'Library', 'Caches', 'puppeteer', 'firefox');
|
|
17
|
+
const dirs = listDirs(f, base).filter((d)=>d.startsWith('mac-') || d.startsWith('mac_arm-'));
|
|
18
|
+
const candidates = [];
|
|
19
|
+
for (const d of dirs){
|
|
20
|
+
candidates.push(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(base, d, 'Firefox.app', 'Contents', 'MacOS', 'firefox'));
|
|
21
|
+
candidates.push(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(base, d, 'Firefox Nightly.app', 'Contents', 'MacOS', 'firefox'));
|
|
22
|
+
}
|
|
23
|
+
return firstExisting(f, candidates);
|
|
24
|
+
}
|
|
25
|
+
if ('win32' === platform) {
|
|
26
|
+
const lad = (null == deps ? void 0 : deps.localAppData) ?? env.LOCALAPPDATA;
|
|
27
|
+
if (!lad) return null;
|
|
28
|
+
const base = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(lad, 'puppeteer', 'firefox');
|
|
29
|
+
const dirs = listDirs(f, base);
|
|
30
|
+
const preferred = [
|
|
31
|
+
...dirs.filter((d)=>d.startsWith('win64-')),
|
|
32
|
+
...dirs.filter((d)=>d.startsWith('win32-'))
|
|
33
|
+
];
|
|
34
|
+
const candidates = [];
|
|
35
|
+
for (const d of preferred){
|
|
36
|
+
candidates.push(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(base, d, 'firefox.exe'));
|
|
37
|
+
candidates.push(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(base, d, 'firefox', 'firefox.exe'));
|
|
38
|
+
}
|
|
39
|
+
return firstExisting(f, candidates);
|
|
40
|
+
}
|
|
41
|
+
const xdg = env.XDG_CACHE_HOME;
|
|
42
|
+
const home = (null == deps ? void 0 : deps.homeDir) ?? env.HOME ?? '';
|
|
43
|
+
const cacheBase = xdg || (home ? __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(home, '.cache') : void 0);
|
|
44
|
+
if (!cacheBase) return null;
|
|
45
|
+
const base = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(cacheBase, 'puppeteer', 'firefox');
|
|
46
|
+
const dirs = listDirs(f, base).filter((d)=>d.startsWith('linux-'));
|
|
47
|
+
const candidates = [];
|
|
48
|
+
for (const d of dirs){
|
|
49
|
+
candidates.push(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(base, d, 'firefox'));
|
|
50
|
+
candidates.push(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(base, d, 'firefox', 'firefox'));
|
|
51
|
+
}
|
|
52
|
+
return firstExisting(f, candidates);
|
|
53
|
+
} catch {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function listDirs(f, dir) {
|
|
58
|
+
try {
|
|
59
|
+
return f.readdirSync(dir, {
|
|
60
|
+
withFileTypes: true
|
|
61
|
+
}).filter((e)=>{
|
|
62
|
+
if (!e) return false;
|
|
63
|
+
const v = e.isDirectory;
|
|
64
|
+
return 'function' == typeof v ? v.call(e) : Boolean(v);
|
|
65
|
+
}).map((e)=>e.name || String(e));
|
|
66
|
+
} catch {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function firstExisting(f, candidates) {
|
|
71
|
+
for (const c of candidates)try {
|
|
72
|
+
if (c && f.existsSync(c)) return c;
|
|
73
|
+
} catch {}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
5
76
|
function locateFirefox(allowFallbackOrDeps, depsMaybe) {
|
|
6
77
|
const isBoolean = 'boolean' == typeof allowFallbackOrDeps;
|
|
7
78
|
const allowFallback = isBoolean ? allowFallbackOrDeps : false;
|
|
@@ -12,10 +83,13 @@ function locateFirefox(allowFallbackOrDeps, depsMaybe) {
|
|
|
12
83
|
const p = (null == deps ? void 0 : deps.path) ?? __WEBPACK_EXTERNAL_MODULE_path__["default"];
|
|
13
84
|
const env = (null == deps ? void 0 : deps.env) ?? process.env;
|
|
14
85
|
const platform = (null == deps ? void 0 : deps.platform) ?? process.platform;
|
|
86
|
+
const override = env.FIREFOX_BINARY;
|
|
87
|
+
if (override && f.existsSync(override)) return override;
|
|
15
88
|
const osx = 'darwin' === platform;
|
|
16
89
|
const win = 'win32' === platform;
|
|
17
90
|
const other = !osx && !win;
|
|
18
91
|
if (other) {
|
|
92
|
+
var _process_env, _process_env1;
|
|
19
93
|
const stable = [
|
|
20
94
|
'firefox'
|
|
21
95
|
];
|
|
@@ -48,9 +122,20 @@ function locateFirefox(allowFallbackOrDeps, depsMaybe) {
|
|
|
48
122
|
];
|
|
49
123
|
for (const linuxPath of linuxPaths)if (f.existsSync(linuxPath)) return linuxPath;
|
|
50
124
|
}
|
|
125
|
+
if (!deps) {
|
|
126
|
+
const viaCache = resolveFromPuppeteerCache();
|
|
127
|
+
if (viaCache) return viaCache;
|
|
128
|
+
}
|
|
129
|
+
const isTestEnv = 'test' === process.env.NODE_ENV || void 0 !== (null == (_process_env = process.env) ? void 0 : _process_env.VITEST) || void 0 !== (null == (_process_env1 = process.env) ? void 0 : _process_env1.JEST_WORKER_ID);
|
|
130
|
+
const skipCliProbe = isTestEnv && 'darwin' === process.platform;
|
|
131
|
+
if (allowFallback && !deps && !skipCliProbe) {
|
|
132
|
+
const viaCLI = resolveFromPuppeteerBrowsersCLI();
|
|
133
|
+
if (viaCLI) return viaCLI;
|
|
134
|
+
}
|
|
51
135
|
return null;
|
|
52
136
|
}
|
|
53
137
|
if (osx) {
|
|
138
|
+
var _process_env2, _process_env3;
|
|
54
139
|
const appsAll = [
|
|
55
140
|
{
|
|
56
141
|
app: 'Firefox.app',
|
|
@@ -80,9 +165,20 @@ function locateFirefox(allowFallbackOrDeps, depsMaybe) {
|
|
|
80
165
|
const userPath = `${userBase}/${app}/Contents/MacOS/${exec}`;
|
|
81
166
|
if (f.existsSync(userPath)) return userPath;
|
|
82
167
|
}
|
|
168
|
+
if (!deps) {
|
|
169
|
+
const viaCache = resolveFromPuppeteerCache();
|
|
170
|
+
if (viaCache) return viaCache;
|
|
171
|
+
}
|
|
172
|
+
const isTestEnv = 'test' === process.env.NODE_ENV || void 0 !== (null == (_process_env2 = process.env) ? void 0 : _process_env2.VITEST) || void 0 !== (null == (_process_env3 = process.env) ? void 0 : _process_env3.JEST_WORKER_ID);
|
|
173
|
+
const skipCliProbe = isTestEnv && 'darwin' === process.platform;
|
|
174
|
+
if (allowFallback && !deps && !skipCliProbe) {
|
|
175
|
+
const viaCLI = resolveFromPuppeteerBrowsersCLI();
|
|
176
|
+
if (viaCLI) return viaCLI;
|
|
177
|
+
}
|
|
83
178
|
return null;
|
|
84
179
|
}
|
|
85
180
|
{
|
|
181
|
+
var _process_env4, _process_env5;
|
|
86
182
|
const prefixes = [
|
|
87
183
|
env.LOCALAPPDATA,
|
|
88
184
|
env.PROGRAMFILES,
|
|
@@ -113,7 +209,80 @@ function locateFirefox(allowFallbackOrDeps, depsMaybe) {
|
|
|
113
209
|
];
|
|
114
210
|
const defaultPaths = allowFallback ? defaultPathsAll : defaultPathsAll.slice(0, 2);
|
|
115
211
|
for (const defaultPath of defaultPaths)if (f.existsSync(defaultPath)) return defaultPath;
|
|
212
|
+
if (!deps) {
|
|
213
|
+
const viaCache = resolveFromPuppeteerCache();
|
|
214
|
+
if (viaCache) return viaCache;
|
|
215
|
+
}
|
|
216
|
+
const isTestEnv = 'test' === process.env.NODE_ENV || void 0 !== (null == (_process_env4 = process.env) ? void 0 : _process_env4.VITEST) || void 0 !== (null == (_process_env5 = process.env) ? void 0 : _process_env5.JEST_WORKER_ID);
|
|
217
|
+
const skipCliProbe = isTestEnv && 'darwin' === process.platform;
|
|
218
|
+
if (allowFallback && !deps && !skipCliProbe) {
|
|
219
|
+
const viaCLI = resolveFromPuppeteerBrowsersCLI();
|
|
220
|
+
if (viaCLI) return viaCLI;
|
|
221
|
+
}
|
|
116
222
|
return null;
|
|
117
223
|
}
|
|
118
224
|
}
|
|
119
|
-
|
|
225
|
+
function getInstallGuidance() {
|
|
226
|
+
return "We couldn't find a Firefox browser on this machine.\n\nHere's the fastest way to get set up:\n\n1) Install Firefox via Puppeteer Browsers (recommended for CI/dev)\n npx @puppeteer/browsers install firefox@stable\n\nThen re-run your command — we will detect it automatically.\n\nAlternatively, install Firefox using your OS package manager and re-run.";
|
|
227
|
+
}
|
|
228
|
+
function locateFirefoxOrExplain(options) {
|
|
229
|
+
const allowFallback = 'boolean' == typeof options ? options : Boolean(null == options ? void 0 : options.allowFallback);
|
|
230
|
+
const found = locateFirefox(allowFallback) || locateFirefox(true);
|
|
231
|
+
if ('string' == typeof found && found) return found;
|
|
232
|
+
throw new Error(getInstallGuidance());
|
|
233
|
+
}
|
|
234
|
+
function resolveFromPuppeteerBrowsersCLI() {
|
|
235
|
+
try {
|
|
236
|
+
const attempts = [
|
|
237
|
+
{
|
|
238
|
+
cmd: 'npx',
|
|
239
|
+
args: [
|
|
240
|
+
'-y',
|
|
241
|
+
'@puppeteer/browsers',
|
|
242
|
+
'path',
|
|
243
|
+
'firefox@stable'
|
|
244
|
+
]
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
cmd: 'pnpm',
|
|
248
|
+
args: [
|
|
249
|
+
'dlx',
|
|
250
|
+
'@puppeteer/browsers',
|
|
251
|
+
'path',
|
|
252
|
+
'firefox@stable'
|
|
253
|
+
]
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
cmd: 'yarn',
|
|
257
|
+
args: [
|
|
258
|
+
'dlx',
|
|
259
|
+
'@puppeteer/browsers',
|
|
260
|
+
'path',
|
|
261
|
+
'firefox@stable'
|
|
262
|
+
]
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
cmd: 'bunx',
|
|
266
|
+
args: [
|
|
267
|
+
'@puppeteer/browsers',
|
|
268
|
+
'path',
|
|
269
|
+
'firefox@stable'
|
|
270
|
+
]
|
|
271
|
+
}
|
|
272
|
+
];
|
|
273
|
+
for (const { cmd, args } of attempts)try {
|
|
274
|
+
const out = (0, __WEBPACK_EXTERNAL_MODULE_child_process__.execFileSync)(cmd, args, {
|
|
275
|
+
encoding: 'utf8',
|
|
276
|
+
stdio: [
|
|
277
|
+
'ignore',
|
|
278
|
+
'pipe',
|
|
279
|
+
'ignore'
|
|
280
|
+
],
|
|
281
|
+
timeout: 2000
|
|
282
|
+
}).trim();
|
|
283
|
+
if (out && __WEBPACK_EXTERNAL_MODULE_fs__["default"].existsSync(out)) return out;
|
|
284
|
+
} catch {}
|
|
285
|
+
} catch {}
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
export { locateFirefox as default, getInstallGuidance, locateFirefoxOrExplain };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
type FsLike = Pick<typeof fs, 'existsSync' | 'readdirSync'>;
|
|
3
|
+
type EnvLike = NodeJS.ProcessEnv;
|
|
4
|
+
export declare function resolveFromPuppeteerCache(deps?: {
|
|
5
|
+
fs?: FsLike;
|
|
6
|
+
env?: EnvLike;
|
|
7
|
+
platform?: NodeJS.Platform;
|
|
8
|
+
homeDir?: string;
|
|
9
|
+
localAppData?: string;
|
|
10
|
+
}): string | null;
|
|
11
|
+
export {};
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"url": "https://github.com/cezaraugusto/firefox-location2.git"
|
|
6
6
|
},
|
|
7
7
|
"name": "firefox-location2",
|
|
8
|
-
"version": "2.0.
|
|
8
|
+
"version": "2.0.4",
|
|
9
9
|
"description": "Approximates the current location of the Firefox browser across platforms.",
|
|
10
10
|
"homepage": "https://www.npmjs.com/package/firefox-location2",
|
|
11
11
|
"type": "module",
|
|
@@ -26,13 +26,17 @@
|
|
|
26
26
|
},
|
|
27
27
|
"scripts": {
|
|
28
28
|
"build": "rslib build",
|
|
29
|
-
"check": "biome check --write",
|
|
29
|
+
"check": "pnpm dlx @biomejs/biome@1.9.4 check --write",
|
|
30
30
|
"dev": "rslib build --watch",
|
|
31
|
-
"format": "biome format --write",
|
|
32
|
-
"test": "vitest run",
|
|
31
|
+
"format": "pnpm dlx @biomejs/biome@1.9.4 format --write",
|
|
32
|
+
"test": "vitest run --pool vmForks --poolOptions.vmForks.singleFork",
|
|
33
33
|
"prepublishOnly": "npm run build",
|
|
34
34
|
"publish:provenance": "np patch --no-tests --any-branch --yolo --message 'release: %s' --provenance"
|
|
35
35
|
},
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=18 <23"
|
|
38
|
+
},
|
|
39
|
+
"engineStrict": true,
|
|
36
40
|
"publishConfig": {
|
|
37
41
|
"provenance": true
|
|
38
42
|
},
|