mirror of
https://github.com/jo-inc/camofox-browser.git
synced 2026-10-02 04:14:41 +08:00
97 lines
3.2 KiB
JavaScript
97 lines
3.2 KiB
JavaScript
#!/usr/bin/env node
|
|
// Download Camoufox at installation time without spawning a shell or `npx`.
|
|
// Failures are warnings so restricted plugin-install environments can still
|
|
// install the JavaScript package and fetch the browser later.
|
|
|
|
import { accessSync, constants, existsSync, statSync } from 'node:fs';
|
|
import { homedir, platform } from 'node:os';
|
|
import { join } from 'node:path';
|
|
import { pathToFileURL } from 'node:url';
|
|
import { downloadBundledCamoufox } from './lib/camoufox-download.js';
|
|
|
|
const EXTERNAL_EXECUTABLE_ENV_VARS = [
|
|
'CAMOUFOX_EXECUTABLE',
|
|
'CAMOUFOX_EXECUTABLE_PATH',
|
|
'CAMOFOX_EXECUTABLE_PATH',
|
|
];
|
|
|
|
function camoufoxCacheDir() {
|
|
const home = homedir();
|
|
const plat = platform();
|
|
if (plat === 'darwin') return join(home, 'Library', 'Caches', 'camoufox');
|
|
if (plat === 'win32') {
|
|
const base = process.env.LOCALAPPDATA || join(home, 'AppData', 'Local');
|
|
return join(base, 'camoufox', 'camoufox', 'Cache');
|
|
}
|
|
return join(process.env.XDG_CACHE_HOME || join(home, '.cache'), 'camoufox');
|
|
}
|
|
|
|
function warn(message) {
|
|
process.stderr.write(`[camofox-browser] postinstall warning: ${message}\n`);
|
|
}
|
|
|
|
function fail(message) {
|
|
warn(message);
|
|
warn('The Camoufox browser binary may not have been downloaded.');
|
|
warn('Run `npx camoufox-js fetch` manually before starting the server.');
|
|
process.exit(0);
|
|
}
|
|
|
|
export function externalExecutableFromEnv(env = process.env) {
|
|
for (const name of EXTERNAL_EXECUTABLE_ENV_VARS) {
|
|
const value = (env[name] || '').trim();
|
|
if (value) return { name, value };
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function assertExternalExecutable(path) {
|
|
if (!existsSync(path)) fail(`external Camoufox executable does not exist: ${path}`);
|
|
const stat = statSync(path);
|
|
if (!stat.isFile()) fail(`external Camoufox executable is not a file: ${path}`);
|
|
if (platform() !== 'win32') {
|
|
try {
|
|
accessSync(path, constants.X_OK);
|
|
} catch {
|
|
fail(`external Camoufox executable is not executable: ${path}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
export async function main() {
|
|
if (process.env.CAMOFOX_SKIP_DOWNLOAD === '1' || process.env.CAMOFOX_SKIP_DOWNLOAD === 'true') {
|
|
process.stderr.write('[camofox-browser] postinstall: skipping binary download (CAMOFOX_SKIP_DOWNLOAD=1)\n');
|
|
return;
|
|
}
|
|
|
|
const externalExecutable = externalExecutableFromEnv();
|
|
if (externalExecutable) {
|
|
assertExternalExecutable(externalExecutable.value);
|
|
process.stdout.write(
|
|
`[camofox-browser] postinstall: ${externalExecutable.name} is set; skipping bundled Camoufox download.\n`
|
|
);
|
|
return;
|
|
}
|
|
|
|
const versionFile = join(camoufoxCacheDir(), 'version.json');
|
|
if (existsSync(versionFile)) {
|
|
process.stdout.write('[camofox-browser] postinstall: Camoufox binary already cached.\n');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await downloadBundledCamoufox();
|
|
} catch (error) {
|
|
fail(`failed to download Camoufox: ${error instanceof Error ? error.message : String(error)}`);
|
|
}
|
|
if (!existsSync(versionFile)) {
|
|
warn('Camoufox cache not populated after fetch.');
|
|
warn(` Expected file: ${versionFile}`);
|
|
warn(' Manual fix: npx camoufox-js fetch');
|
|
}
|
|
}
|
|
|
|
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
main().catch(() => process.exit(0));
|
|
}
|