First Commit

This commit is contained in:
2025-08-28 19:35:28 -07:00
commit 264e65006a
488 changed files with 155661 additions and 0 deletions

View File

@@ -0,0 +1,175 @@
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var browserFetcher_exports = {};
__export(browserFetcher_exports, {
downloadBrowserWithProgressBar: () => downloadBrowserWithProgressBar,
logPolitely: () => logPolitely
});
module.exports = __toCommonJS(browserFetcher_exports);
var childProcess = __toESM(require("child_process"));
var import_fs = __toESM(require("fs"));
var import_os = __toESM(require("os"));
var import_path = __toESM(require("path"));
var import_debugLogger = require("../utils/debugLogger");
var import_manualPromise = require("../../utils/isomorphic/manualPromise");
var import_userAgent = require("../utils/userAgent");
var import_utilsBundle = require("../../utilsBundle");
var import_fileUtils = require("../utils/fileUtils");
var import__ = require(".");
async function downloadBrowserWithProgressBar(title, browserDirectory, executablePath, downloadURLs, downloadFileName, downloadSocketTimeout) {
if (await (0, import_fileUtils.existsAsync)((0, import__.browserDirectoryToMarkerFilePath)(browserDirectory))) {
import_debugLogger.debugLogger.log("install", `${title} is already downloaded.`);
return false;
}
const zipPath = import_path.default.join(import_os.default.tmpdir(), downloadFileName);
try {
const retryCount = 5;
for (let attempt = 1; attempt <= retryCount; ++attempt) {
import_debugLogger.debugLogger.log("install", `downloading ${title} - attempt #${attempt}`);
const url = downloadURLs[(attempt - 1) % downloadURLs.length];
logPolitely(`Downloading ${title}` + import_utilsBundle.colors.dim(` from ${url}`));
const { error } = await downloadBrowserWithProgressBarOutOfProcess(title, browserDirectory, url, zipPath, executablePath, downloadSocketTimeout);
if (!error) {
import_debugLogger.debugLogger.log("install", `SUCCESS installing ${title}`);
break;
}
if (await (0, import_fileUtils.existsAsync)(zipPath))
await import_fs.default.promises.unlink(zipPath);
if (await (0, import_fileUtils.existsAsync)(browserDirectory))
await import_fs.default.promises.rmdir(browserDirectory, { recursive: true });
const errorMessage = error?.message || "";
import_debugLogger.debugLogger.log("install", `attempt #${attempt} - ERROR: ${errorMessage}`);
if (attempt >= retryCount)
throw error;
}
} catch (e) {
import_debugLogger.debugLogger.log("install", `FAILED installation ${title} with error: ${e}`);
process.exitCode = 1;
throw e;
} finally {
if (await (0, import_fileUtils.existsAsync)(zipPath))
await import_fs.default.promises.unlink(zipPath);
}
logPolitely(`${title} downloaded to ${browserDirectory}`);
return true;
}
function downloadBrowserWithProgressBarOutOfProcess(title, browserDirectory, url, zipPath, executablePath, socketTimeout) {
const cp = childProcess.fork(import_path.default.join(__dirname, "oopDownloadBrowserMain.js"));
const promise = new import_manualPromise.ManualPromise();
const progress = getDownloadProgress();
cp.on("message", (message) => {
if (message?.method === "log")
import_debugLogger.debugLogger.log("install", message.params.message);
if (message?.method === "progress")
progress(message.params.done, message.params.total);
});
cp.on("exit", (code) => {
if (code !== 0) {
promise.resolve({ error: new Error(`Download failure, code=${code}`) });
return;
}
if (!import_fs.default.existsSync((0, import__.browserDirectoryToMarkerFilePath)(browserDirectory)))
promise.resolve({ error: new Error(`Download failure, ${(0, import__.browserDirectoryToMarkerFilePath)(browserDirectory)} does not exist`) });
else
promise.resolve({ error: null });
});
cp.on("error", (error) => {
promise.resolve({ error });
});
import_debugLogger.debugLogger.log("install", `running download:`);
import_debugLogger.debugLogger.log("install", `-- from url: ${url}`);
import_debugLogger.debugLogger.log("install", `-- to location: ${zipPath}`);
const downloadParams = {
title,
browserDirectory,
url,
zipPath,
executablePath,
socketTimeout,
userAgent: (0, import_userAgent.getUserAgent)()
};
cp.send({ method: "download", params: downloadParams });
return promise;
}
function logPolitely(toBeLogged) {
const logLevel = process.env.npm_config_loglevel;
const logLevelDisplay = ["silent", "error", "warn"].indexOf(logLevel || "") > -1;
if (!logLevelDisplay)
console.log(toBeLogged);
}
function getDownloadProgress() {
if (process.stdout.isTTY)
return getAnimatedDownloadProgress();
return getBasicDownloadProgress();
}
function getAnimatedDownloadProgress() {
let progressBar;
let lastDownloadedBytes = 0;
return (downloadedBytes, totalBytes) => {
if (!progressBar) {
progressBar = new import_utilsBundle.progress(
`${toMegabytes(
totalBytes
)} [:bar] :percent :etas`,
{
complete: "=",
incomplete: " ",
width: 20,
total: totalBytes
}
);
}
const delta = downloadedBytes - lastDownloadedBytes;
lastDownloadedBytes = downloadedBytes;
progressBar.tick(delta);
};
}
function getBasicDownloadProgress() {
const totalRows = 10;
const stepWidth = 8;
let lastRow = -1;
return (downloadedBytes, totalBytes) => {
const percentage = downloadedBytes / totalBytes;
const row = Math.floor(totalRows * percentage);
if (row > lastRow) {
lastRow = row;
const percentageString = String(percentage * 100 | 0).padStart(3);
console.log(`|${"\u25A0".repeat(row * stepWidth)}${" ".repeat((totalRows - row) * stepWidth)}| ${percentageString}% of ${toMegabytes(totalBytes)}`);
}
};
}
function toMegabytes(bytes) {
const mb = bytes / 1024 / 1024;
return `${Math.round(mb * 10) / 10} MiB`;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
downloadBrowserWithProgressBar,
logPolitely
});

View File

@@ -0,0 +1,371 @@
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var dependencies_exports = {};
__export(dependencies_exports, {
dockerVersion: () => dockerVersion,
installDependenciesLinux: () => installDependenciesLinux,
installDependenciesWindows: () => installDependenciesWindows,
readDockerVersionSync: () => readDockerVersionSync,
transformCommandsForRoot: () => transformCommandsForRoot,
validateDependenciesLinux: () => validateDependenciesLinux,
validateDependenciesWindows: () => validateDependenciesWindows,
writeDockerVersion: () => writeDockerVersion
});
module.exports = __toCommonJS(dependencies_exports);
var childProcess = __toESM(require("child_process"));
var import_fs = __toESM(require("fs"));
var import_os = __toESM(require("os"));
var import_path = __toESM(require("path"));
var import_nativeDeps = require("./nativeDeps");
var import_ascii = require("../utils/ascii");
var import_hostPlatform = require("../utils/hostPlatform");
var import_spawnAsync = require("../utils/spawnAsync");
var import_userAgent = require("../utils/userAgent");
var import__ = require(".");
const BIN_DIRECTORY = import_path.default.join(__dirname, "..", "..", "..", "bin");
const languageBindingVersion = process.env.PW_CLI_DISPLAY_VERSION || require("../../../package.json").version;
const dockerVersionFilePath = "/ms-playwright/.docker-info";
async function writeDockerVersion(dockerImageNameTemplate) {
await import_fs.default.promises.mkdir(import_path.default.dirname(dockerVersionFilePath), { recursive: true });
await import_fs.default.promises.writeFile(dockerVersionFilePath, JSON.stringify(dockerVersion(dockerImageNameTemplate), null, 2), "utf8");
await import_fs.default.promises.chmod(dockerVersionFilePath, 511);
}
function dockerVersion(dockerImageNameTemplate) {
return {
driverVersion: languageBindingVersion,
dockerImageName: dockerImageNameTemplate.replace("%version%", languageBindingVersion)
};
}
function readDockerVersionSync() {
try {
const data = JSON.parse(import_fs.default.readFileSync(dockerVersionFilePath, "utf8"));
return {
...data,
dockerImageNameTemplate: data.dockerImageName.replace(data.driverVersion, "%version%")
};
} catch (e) {
return null;
}
}
const checkExecutable = (filePath) => {
if (process.platform === "win32")
return filePath.endsWith(".exe");
return import_fs.default.promises.access(filePath, import_fs.default.constants.X_OK).then(() => true).catch(() => false);
};
function isSupportedWindowsVersion() {
if (import_os.default.platform() !== "win32" || import_os.default.arch() !== "x64")
return false;
const [major, minor] = import_os.default.release().split(".").map((token) => parseInt(token, 10));
return major > 6 || major === 6 && minor > 1;
}
async function installDependenciesWindows(targets, dryRun) {
if (targets.has("chromium")) {
const command = "powershell.exe";
const args = ["-ExecutionPolicy", "Bypass", "-File", import_path.default.join(BIN_DIRECTORY, "install_media_pack.ps1")];
if (dryRun) {
console.log(`${command} ${quoteProcessArgs(args).join(" ")}`);
return;
}
const { code } = await (0, import_spawnAsync.spawnAsync)(command, args, { cwd: BIN_DIRECTORY, stdio: "inherit" });
if (code !== 0)
throw new Error("Failed to install windows dependencies!");
}
}
async function installDependenciesLinux(targets, dryRun) {
const libraries = [];
const platform = import_hostPlatform.hostPlatform;
if (!import_hostPlatform.isOfficiallySupportedPlatform)
console.warn(`BEWARE: your OS is not officially supported by Playwright; installing dependencies for ${platform} as a fallback.`);
for (const target of targets) {
const info = import_nativeDeps.deps[platform];
if (!info) {
console.warn(`Cannot install dependencies for ${platform} with Playwright ${(0, import_userAgent.getPlaywrightVersion)()}!`);
return;
}
libraries.push(...info[target]);
}
const uniqueLibraries = Array.from(new Set(libraries));
if (!dryRun)
console.log(`Installing dependencies...`);
const commands = [];
commands.push("apt-get update");
commands.push([
"apt-get",
"install",
"-y",
"--no-install-recommends",
...uniqueLibraries
].join(" "));
const { command, args, elevatedPermissions } = await transformCommandsForRoot(commands);
if (dryRun) {
console.log(`${command} ${quoteProcessArgs(args).join(" ")}`);
return;
}
if (elevatedPermissions)
console.log("Switching to root user to install dependencies...");
const child = childProcess.spawn(command, args, { stdio: "inherit" });
await new Promise((resolve, reject) => {
child.on("exit", (code) => code === 0 ? resolve() : reject(new Error(`Installation process exited with code: ${code}`)));
child.on("error", reject);
});
}
async function validateDependenciesWindows(sdkLanguage, windowsExeAndDllDirectories) {
const directoryPaths = windowsExeAndDllDirectories;
const lddPaths = [];
for (const directoryPath of directoryPaths)
lddPaths.push(...await executablesOrSharedLibraries(directoryPath));
const allMissingDeps = await Promise.all(lddPaths.map((lddPath) => missingFileDependenciesWindows(sdkLanguage, lddPath)));
const missingDeps = /* @__PURE__ */ new Set();
for (const deps2 of allMissingDeps) {
for (const dep of deps2)
missingDeps.add(dep);
}
if (!missingDeps.size)
return;
let isCrtMissing = false;
let isMediaFoundationMissing = false;
for (const dep of missingDeps) {
if (dep.startsWith("api-ms-win-crt") || dep === "vcruntime140.dll" || dep === "vcruntime140_1.dll" || dep === "msvcp140.dll")
isCrtMissing = true;
else if (dep === "mf.dll" || dep === "mfplat.dll" || dep === "msmpeg2vdec.dll" || dep === "evr.dll" || dep === "avrt.dll")
isMediaFoundationMissing = true;
}
const details = [];
if (isCrtMissing) {
details.push(
`Some of the Universal C Runtime files cannot be found on the system. You can fix`,
`that by installing Microsoft Visual C++ Redistributable for Visual Studio from:`,
`https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads`,
``
);
}
if (isMediaFoundationMissing) {
details.push(
`Some of the Media Foundation files cannot be found on the system. If you are`,
`on Windows Server try fixing this by running the following command in PowerShell`,
`as Administrator:`,
``,
` Install-WindowsFeature Server-Media-Foundation`,
``,
`For Windows N editions visit:`,
`https://support.microsoft.com/en-us/help/3145500/media-feature-pack-list-for-windows-n-editions`,
``
);
}
details.push(
`Full list of missing libraries:`,
` ${[...missingDeps].join("\n ")}`,
``
);
const message = `Host system is missing dependencies!
${details.join("\n")}`;
if (isSupportedWindowsVersion()) {
throw new Error(message);
} else {
console.warn(`WARNING: running on unsupported windows version!`);
console.warn(message);
}
}
async function validateDependenciesLinux(sdkLanguage, linuxLddDirectories, dlOpenLibraries) {
const directoryPaths = linuxLddDirectories;
const lddPaths = [];
for (const directoryPath of directoryPaths)
lddPaths.push(...await executablesOrSharedLibraries(directoryPath));
const missingDepsPerFile = await Promise.all(lddPaths.map((lddPath) => missingFileDependencies(lddPath, directoryPaths)));
const missingDeps = /* @__PURE__ */ new Set();
for (const deps2 of missingDepsPerFile) {
for (const dep of deps2)
missingDeps.add(dep);
}
for (const dep of await missingDLOPENLibraries(dlOpenLibraries))
missingDeps.add(dep);
if (!missingDeps.size)
return;
const allMissingDeps = new Set(missingDeps);
const missingPackages = /* @__PURE__ */ new Set();
const libraryToPackageNameMapping = import_nativeDeps.deps[import_hostPlatform.hostPlatform] ? {
...import_nativeDeps.deps[import_hostPlatform.hostPlatform]?.lib2package || {},
...MANUAL_LIBRARY_TO_PACKAGE_NAME_UBUNTU
} : {};
for (const missingDep of missingDeps) {
const packageName = libraryToPackageNameMapping[missingDep];
if (packageName) {
missingPackages.add(packageName);
missingDeps.delete(missingDep);
}
}
const maybeSudo = process.getuid?.() && import_os.default.platform() !== "win32" ? "sudo " : "";
const dockerInfo = readDockerVersionSync();
const errorLines = [
`Host system is missing dependencies to run browsers.`
];
if (dockerInfo && !dockerInfo.driverVersion.startsWith((0, import_userAgent.getPlaywrightVersion)(
true
/* majorMinorOnly */
) + ".")) {
const pwVersion = (0, import_userAgent.getPlaywrightVersion)();
const requiredDockerImage = dockerInfo.dockerImageName.replace(dockerInfo.driverVersion, pwVersion);
errorLines.push(...[
`This is most likely due to Docker image version not matching Playwright version:`,
`- Playwright : ${pwVersion}`,
`- Docker image: ${dockerInfo.driverVersion}`,
``,
`Either:`,
`- (recommended) use Docker image "${requiredDockerImage}"`,
`- (alternative 1) run the following command inside Docker to install missing dependencies:`,
``,
` ${maybeSudo}${(0, import__.buildPlaywrightCLICommand)(sdkLanguage, "install-deps")}`,
``,
`- (alternative 2) use apt inside Docker:`,
``,
` ${maybeSudo}apt-get install ${[...missingPackages].join("\\\n ")}`,
``,
`<3 Playwright Team`
]);
} else if (missingPackages.size && !missingDeps.size) {
errorLines.push(...[
`Please install them with the following command:`,
``,
` ${maybeSudo}${(0, import__.buildPlaywrightCLICommand)(sdkLanguage, "install-deps")}`,
``,
`Alternatively, use apt:`,
` ${maybeSudo}apt-get install ${[...missingPackages].join("\\\n ")}`,
``,
`<3 Playwright Team`
]);
} else {
errorLines.push(...[
`Missing libraries:`,
...[...allMissingDeps].map((dep) => " " + dep)
]);
}
throw new Error("\n" + (0, import_ascii.wrapInASCIIBox)(errorLines.join("\n"), 1));
}
function isSharedLib(basename) {
switch (import_os.default.platform()) {
case "linux":
return basename.endsWith(".so") || basename.includes(".so.");
case "win32":
return basename.endsWith(".dll");
default:
return false;
}
}
async function executablesOrSharedLibraries(directoryPath) {
if (!import_fs.default.existsSync(directoryPath))
return [];
const allPaths = (await import_fs.default.promises.readdir(directoryPath)).map((file) => import_path.default.resolve(directoryPath, file));
const allStats = await Promise.all(allPaths.map((aPath) => import_fs.default.promises.stat(aPath)));
const filePaths = allPaths.filter((aPath, index) => allStats[index].isFile());
const executablersOrLibraries = (await Promise.all(filePaths.map(async (filePath) => {
const basename = import_path.default.basename(filePath).toLowerCase();
if (isSharedLib(basename))
return filePath;
if (await checkExecutable(filePath))
return filePath;
return false;
}))).filter(Boolean);
return executablersOrLibraries;
}
async function missingFileDependenciesWindows(sdkLanguage, filePath) {
const executable = import__.registry.findExecutable("winldd").executablePathOrDie(sdkLanguage);
const dirname = import_path.default.dirname(filePath);
const { stdout, code } = await (0, import_spawnAsync.spawnAsync)(executable, [filePath], {
cwd: dirname,
env: {
...process.env,
LD_LIBRARY_PATH: process.env.LD_LIBRARY_PATH ? `${process.env.LD_LIBRARY_PATH}:${dirname}` : dirname
}
});
if (code !== 0)
return [];
const missingDeps = stdout.split("\n").map((line) => line.trim()).filter((line) => line.endsWith("not found") && line.includes("=>")).map((line) => line.split("=>")[0].trim().toLowerCase());
return missingDeps;
}
async function missingFileDependencies(filePath, extraLDPaths) {
const dirname = import_path.default.dirname(filePath);
let LD_LIBRARY_PATH = extraLDPaths.join(":");
if (process.env.LD_LIBRARY_PATH)
LD_LIBRARY_PATH = `${process.env.LD_LIBRARY_PATH}:${LD_LIBRARY_PATH}`;
const { stdout, code } = await (0, import_spawnAsync.spawnAsync)("ldd", [filePath], {
cwd: dirname,
env: {
...process.env,
LD_LIBRARY_PATH
}
});
if (code !== 0)
return [];
const missingDeps = stdout.split("\n").map((line) => line.trim()).filter((line) => line.endsWith("not found") && line.includes("=>")).map((line) => line.split("=>")[0].trim());
return missingDeps;
}
async function missingDLOPENLibraries(libraries) {
if (!libraries.length)
return [];
const { stdout, code, error } = await (0, import_spawnAsync.spawnAsync)("/sbin/ldconfig", ["-p"], {});
if (code !== 0 || error)
return [];
const isLibraryAvailable = (library) => stdout.toLowerCase().includes(library.toLowerCase());
return libraries.filter((library) => !isLibraryAvailable(library));
}
const MANUAL_LIBRARY_TO_PACKAGE_NAME_UBUNTU = {
// libgstlibav.so (the only actual library provided by gstreamer1.0-libav) is not
// in the ldconfig cache, so we detect the actual library required for playing h.264
// and if it's missing recommend installing missing gstreamer lib.
// gstreamer1.0-libav -> libavcodec57 -> libx264-152
"libx264.so": "gstreamer1.0-libav"
};
function quoteProcessArgs(args) {
return args.map((arg) => {
if (arg.includes(" "))
return `"${arg}"`;
return arg;
});
}
async function transformCommandsForRoot(commands) {
const isRoot = process.getuid?.() === 0;
if (isRoot)
return { command: "sh", args: ["-c", `${commands.join("&& ")}`], elevatedPermissions: false };
const sudoExists = await (0, import_spawnAsync.spawnAsync)("which", ["sudo"]);
if (sudoExists.code === 0)
return { command: "sudo", args: ["--", "sh", "-c", `${commands.join("&& ")}`], elevatedPermissions: true };
return { command: "su", args: ["root", "-c", `${commands.join("&& ")}`], elevatedPermissions: true };
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
dockerVersion,
installDependenciesLinux,
installDependenciesWindows,
readDockerVersionSync,
transformCommandsForRoot,
validateDependenciesLinux,
validateDependenciesWindows,
writeDockerVersion
});

1306
node_modules/playwright-core/lib/server/registry/index.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,120 @@
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var oopDownloadBrowserMain_exports = {};
module.exports = __toCommonJS(oopDownloadBrowserMain_exports);
var import_fs = __toESM(require("fs"));
var import_path = __toESM(require("path"));
var import_manualPromise = require("../../utils/isomorphic/manualPromise");
var import_network = require("../utils/network");
var import_zipBundle = require("../../zipBundle");
function log(message) {
process.send?.({ method: "log", params: { message } });
}
function progress(done, total) {
process.send?.({ method: "progress", params: { done, total } });
}
function browserDirectoryToMarkerFilePath(browserDirectory) {
return import_path.default.join(browserDirectory, "INSTALLATION_COMPLETE");
}
function downloadFile(options) {
let downloadedBytes = 0;
let totalBytes = 0;
const promise = new import_manualPromise.ManualPromise();
(0, import_network.httpRequest)({
url: options.url,
headers: {
"User-Agent": options.userAgent
},
socketTimeout: options.socketTimeout
}, (response) => {
log(`-- response status code: ${response.statusCode}`);
if (response.statusCode !== 200) {
let content = "";
const handleError = () => {
const error = new Error(`Download failed: server returned code ${response.statusCode} body '${content}'. URL: ${options.url}`);
response.resume();
promise.reject(error);
};
response.on("data", (chunk) => content += chunk).on("end", handleError).on("error", handleError);
return;
}
totalBytes = parseInt(response.headers["content-length"] || "0", 10);
log(`-- total bytes: ${totalBytes}`);
const file = import_fs.default.createWriteStream(options.zipPath);
file.on("finish", () => {
if (downloadedBytes !== totalBytes) {
log(`-- download failed, size mismatch: ${downloadedBytes} != ${totalBytes}`);
promise.reject(new Error(`Download failed: size mismatch, file size: ${downloadedBytes}, expected size: ${totalBytes} URL: ${options.url}`));
} else {
log(`-- download complete, size: ${downloadedBytes}`);
promise.resolve();
}
});
file.on("error", (error) => promise.reject(error));
response.pipe(file);
response.on("data", onData);
response.on("error", (error) => {
file.close();
if (error?.code === "ECONNRESET") {
log(`-- download failed, server closed connection`);
promise.reject(new Error(`Download failed: server closed connection. URL: ${options.url}`));
} else {
log(`-- download failed, unexpected error`);
promise.reject(new Error(`Download failed: ${error?.message ?? error}. URL: ${options.url}`));
}
});
}, (error) => promise.reject(error));
return promise;
function onData(chunk) {
downloadedBytes += chunk.length;
progress(downloadedBytes, totalBytes);
}
}
async function main(options) {
await downloadFile(options);
log(`SUCCESS downloading ${options.title}`);
log(`extracting archive`);
await (0, import_zipBundle.extract)(options.zipPath, { dir: options.browserDirectory });
if (options.executablePath) {
log(`fixing permissions at ${options.executablePath}`);
await import_fs.default.promises.chmod(options.executablePath, 493);
}
await import_fs.default.promises.writeFile(browserDirectoryToMarkerFilePath(options.browserDirectory), "");
}
process.on("message", async (message) => {
const { method, params } = message;
if (method === "download") {
try {
await main(params);
process.exit(0);
} catch (e) {
console.error(e);
process.exit(1);
}
}
});
process.on("disconnect", () => {
process.exit(0);
});