#!/usr/bin/env node

// src/utils/atomic-file.ts
import { constants as fsConstants, promises as fs } from "fs";
import path from "path";
import crypto from "crypto";
async function atomicWriteFile(targetPath, contents, options = {}) {
  if (contents.length === 0) {
    throw new Error(
      `Refusing to atomicWriteFile an empty payload to ${targetPath}`
    );
  }
  const mode = options.mode ?? 384;
  const shouldFsync = options.fsync ?? true;
  const dir = path.dirname(targetPath);
  await fs.mkdir(dir, { recursive: true });
  const suffix = crypto.randomBytes(6).toString("hex");
  const tmpPath = `${targetPath}.tmp-${process.pid}-${suffix}`;
  const fh = await fs.open(
    tmpPath,
    fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL,
    mode
  );
  try {
    await fh.writeFile(contents, "utf8");
    try {
      await fh.chmod(mode);
    } catch {
    }
    if (shouldFsync) {
      try {
        await fh.sync();
      } catch {
      }
    }
  } finally {
    await fh.close();
  }
  try {
    await fs.rename(tmpPath, targetPath);
  } catch (err) {
    await fs.unlink(tmpPath).catch(() => void 0);
    throw err;
  }
}
async function withFileLock(lockPath, fn, options = {}) {
  const retries = options.retries ?? 100;
  const minDelayMs = options.minDelayMs ?? 20;
  const maxDelayMs = options.maxDelayMs ?? 200;
  const staleMs = options.staleMs ?? 3e4;
  await fs.mkdir(path.dirname(lockPath), { recursive: true });
  let attempt = 0;
  let acquired = false;
  while (!acquired) {
    try {
      const fh = await fs.open(
        lockPath,
        fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL,
        384
      );
      await fh.writeFile(`${process.pid}
`, "utf8");
      await fh.close();
      acquired = true;
      break;
    } catch (err) {
      const code = err.code;
      if (code !== "EEXIST") {
        throw err;
      }
    }
    let stat = null;
    try {
      stat = await fs.stat(lockPath);
    } catch {
      continue;
    }
    if (stat !== null) {
      const ageMs = Date.now() - stat.mtimeMs;
      if (ageMs > staleMs) {
        await fs.unlink(lockPath).catch(() => void 0);
        continue;
      }
    }
    attempt += 1;
    if (attempt >= retries) {
      throw new Error(
        `Timed out acquiring file lock at ${lockPath} after ${retries} attempts.`
      );
    }
    const jitter = Math.floor(
      Math.random() * Math.max(1, maxDelayMs - minDelayMs)
    );
    await new Promise((resolve) => setTimeout(resolve, minDelayMs + jitter));
  }
  try {
    return await fn();
  } finally {
    await fs.unlink(lockPath).catch(() => void 0);
  }
}

export {
  atomicWriteFile,
  withFileLock
};
//# sourceMappingURL=chunk-TAEQKBJB.mjs.map