"use strict";
/* Socket Lib - Built with esbuild */
"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 binary_download_exports = {};
__export(binary_download_exports, {
  downloadBinary: () => downloadBinary,
  downloadBinaryFile: () => downloadBinaryFile
});
module.exports = __toCommonJS(binary_download_exports);
var import_node_process = __toESM(require("node:process"));
var import_platform = require("../constants/platform");
var import_time = require("../constants/time");
var import_hash = require("../crypto/hash");
var import_safe = require("../fs/safe");
var import_download = require("../http-request/download");
var import_normalize = require("../paths/normalize");
var import_lock_instance = require("../process/lock-instance");
var import_cache = require("./cache");
var import_integrity = require("../integrity");
var import_error = require("../primordials/error");
var import_crypto = require("../node/crypto");
var import_fs = require("../node/fs");
var import_path = require("../node/path");
var import_binary_cache = require("./binary-cache");
async function downloadBinary(options) {
  const {
    cacheTtl = import_time.DLX_BINARY_CACHE_TTL,
    force = false,
    hash: hashSpec,
    integrity: rawIntegrity,
    name,
    sha256: rawSha256,
    url
  } = { __proto__: null, ...options };
  let integrity = rawIntegrity;
  let sha256 = rawSha256;
  if (hashSpec !== void 0) {
    const normalized = (0, import_integrity.normalizeHash)(hashSpec);
    if (normalized.type === "integrity") {
      integrity = normalized.value;
    } else {
      sha256 = normalized.value;
    }
  }
  const fs = (0, import_fs.getNodeFs)();
  const path = (0, import_path.getNodePath)();
  const cacheDir = (0, import_binary_cache.getDlxCachePath)();
  const binaryName = name || `binary-${import_node_process.default.platform}-${(0, import_platform.getArch)()}`;
  const spec = `${url}:${binaryName}`;
  const cacheKey = (0, import_cache.generateCacheKey)(spec);
  const cacheEntryDir = path.join(cacheDir, cacheKey);
  const binaryPath = (0, import_normalize.normalizePath)(path.join(cacheEntryDir, binaryName));
  let downloaded = false;
  let actualIntegrity = "";
  if (!force && fs.existsSync(cacheEntryDir) && await (0, import_binary_cache.isBinaryCacheValid)(cacheEntryDir, cacheTtl)) {
    downloaded = false;
    const cachedMeta = await (0, import_binary_cache.readBinaryCacheMetadata)(cacheEntryDir);
    if (cachedMeta?.integrity) {
      actualIntegrity = cachedMeta.integrity;
    } else {
      const fileBuffer = await fs.promises.readFile(binaryPath);
      actualIntegrity = `sha512-${(0, import_hash.hash)("sha512", fileBuffer, "base64")}`;
    }
  } else {
    try {
      await (0, import_safe.safeMkdir)(cacheEntryDir);
    } catch (e) {
      const code = e.code;
      if (code === "EACCES" || code === "EPERM") {
        throw new import_error.ErrorCtor(
          `Permission denied creating binary cache directory: ${cacheEntryDir}
Please check directory permissions or run with appropriate access.`,
          { cause: e }
        );
      }
      if (code === "EROFS") {
        throw new import_error.ErrorCtor(
          `Cannot create binary cache directory on read-only filesystem: ${cacheEntryDir}
Ensure the filesystem is writable or set SOCKET_DLX_DIR to a writable location.`,
          { cause: e }
        );
      }
      throw new import_error.ErrorCtor(
        `Failed to create binary cache directory: ${cacheEntryDir}`,
        { cause: e }
      );
    }
    actualIntegrity = await downloadBinaryFile(
      url,
      binaryPath,
      integrity,
      sha256
    );
    const stats = await fs.promises.stat(binaryPath);
    await (0, import_binary_cache.writeBinaryCacheMetadata)(
      cacheEntryDir,
      cacheKey,
      url,
      actualIntegrity,
      stats.size
    );
    downloaded = true;
  }
  return {
    binaryPath,
    downloaded,
    integrity: actualIntegrity
  };
}
async function downloadBinaryFile(url, destPath, integrity, sha256) {
  const crypto = (0, import_crypto.getNodeCrypto)();
  const fs = (0, import_fs.getNodeFs)();
  const path = (0, import_path.getNodePath)();
  const cacheEntryDir = path.dirname(destPath);
  const lockPath = path.join(cacheEntryDir, "concurrency.lock");
  const verifyIntegrity = async (actualIntegrity) => {
    if (!integrity) {
      return;
    }
    const integrityMatch = actualIntegrity.length === integrity.length && crypto.timingSafeEqual(
      Buffer.from(actualIntegrity),
      Buffer.from(integrity)
    );
    if (!integrityMatch) {
      await (0, import_safe.safeDelete)(destPath);
      throw new import_error.ErrorCtor(
        `Integrity mismatch: expected ${integrity}, got ${actualIntegrity}`
      );
    }
  };
  const verifyCachedSha256 = async (fileBuffer) => {
    if (!sha256) {
      return;
    }
    const actualSha256 = (0, import_hash.hash)("sha256", fileBuffer, "hex");
    const sha256Match = actualSha256.length === sha256.length && crypto.timingSafeEqual(
      Buffer.from(actualSha256),
      Buffer.from(sha256.toLowerCase())
    );
    if (!sha256Match) {
      await (0, import_safe.safeDelete)(destPath);
      throw new import_error.ErrorCtor(
        `SHA-256 mismatch: expected ${sha256}, got ${actualSha256}`
      );
    }
  };
  return await import_lock_instance.processLock.withLock(
    lockPath,
    async () => {
      if (fs.existsSync(destPath)) {
        const stats = await fs.promises.stat(destPath);
        if (stats.size > 0) {
          const fileBuffer2 = await fs.promises.readFile(destPath);
          const actualIntegrity2 = `sha512-${(0, import_hash.hash)("sha512", fileBuffer2, "base64")}`;
          await verifyIntegrity(actualIntegrity2);
          await verifyCachedSha256(fileBuffer2);
          return actualIntegrity2;
        }
      }
      try {
        await (0, import_download.httpDownload)(url, destPath, sha256 ? { sha256 } : void 0);
      } catch (e) {
        throw new import_error.ErrorCtor(
          `Failed to download binary from ${url}
Destination: ${destPath}
Check your internet connection or verify the URL is accessible.`,
          { cause: e }
        );
      }
      const fileBuffer = await fs.promises.readFile(destPath);
      const actualIntegrity = `sha512-${(0, import_hash.hash)("sha512", fileBuffer, "base64")}`;
      await verifyIntegrity(actualIntegrity);
      if (!import_platform.WIN32) {
        await fs.promises.chmod(destPath, 493);
      }
      return actualIntegrity;
    },
    {
      // Align with npm npx locking strategy.
      staleMs: 5e3,
      touchIntervalMs: 2e3
    }
  );
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  downloadBinary,
  downloadBinaryFile
});
