/**
 * 原子写入工具 — 先写 .tmp 再 rename，保证读者不会看到半写文件。
 *
 * 参考 task_context/manager.ts:save() 的 tmp+rename 模式：
 * - 使用唯一 ID 后缀避免并发写入同一 .tmp 文件
 * - rename 在文件系统层面保证原子性
 * - 写入失败时 best-effort 清理 .tmp 文件
 */
import fs from "node:fs";
import fsp from "node:fs/promises";
import path from "node:path";
import crypto from "node:crypto";
import { debug } from "./logger.js";
/**
 * 同步原子写入：先写 .tmp 再 rename。
 *
 * @param filePath - 目标文件路径
 * @param content - 要写入的内容
 * @param encoding - 编码，默认 "utf-8"
 */
export function atomicWriteFileSync(filePath, content, encoding = "utf-8") {
    // 确保父目录存在
    const dir = path.dirname(filePath);
    fs.mkdirSync(dir, { recursive: true });
    // 使用随机 ID 后缀避免并发写入冲突
    const tmpPath = `${filePath}.${crypto.randomUUID().slice(0, 8)}.tmp`;
    try {
        fs.writeFileSync(tmpPath, content, encoding);
        fs.renameSync(tmpPath, filePath);
    }
    catch (e) {
        // best-effort 清理临时文件
        try {
            fs.unlinkSync(tmpPath);
        }
        catch { }
        throw e;
    }
}
/**
 * 异步原子写入：先写 .tmp 再 rename。
 *
 * @param filePath - 目标文件路径
 * @param content - 要写入的内容
 * @param encoding - 编码，默认 "utf-8"
 */
export async function atomicWriteFile(filePath, content, encoding = "utf-8") {
    // 确保父目录存在
    const dir = path.dirname(filePath);
    await fsp.mkdir(dir, { recursive: true });
    // 使用随机 ID 后缀避免并发写入冲突
    const tmpPath = `${filePath}.${crypto.randomUUID().slice(0, 8)}.tmp`;
    try {
        await fsp.writeFile(tmpPath, content, encoding);
        await fsp.rename(tmpPath, filePath);
    }
    catch (e) {
        // best-effort 清理临时文件
        await fsp.unlink(tmpPath).catch((e) => { debug("原子写入", "清理临时文件失败", e); });
        throw e;
    }
}
//# sourceMappingURL=write_file_atomic.js.map