"use strict";
/**
 * Atomic JSON file writes via temp-file + rename.
 *
 * writeFileSync is atomic for small files on POSIX, but NOT on Windows.
 * This utility ensures crash-safety on all platforms: if the process dies
 * mid-write, the original file is untouched (the temp file is orphaned).
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.atomicWriteJSON = atomicWriteJSON;
const fs_1 = require("fs");
/**
 * Write a JSON object to a file atomically.
 *
 * 1. Writes to a temp file (same directory, PID-suffixed)
 * 2. Renames temp → target (atomic on all OSes)
 * 3. If `mode` is set, chmods the destination so a previously-existing
 *    file at a looser mode is tightened. Without this step, a stale
 *    `~/.ampli.json` created at 0o644 by an older wizard would silently
 *    keep that mode forever, leaking OAuth tokens to other local users.
 * 4. Cleans up temp on failure
 *
 * Backwards-compatibility shim: callers may still pass a numeric mode as
 * the third positional arg. New callers should pass `{ mode }`.
 */
function atomicWriteJSON(filePath, data, modeOrOptions) {
    const options = typeof modeOrOptions === 'number'
        ? { mode: modeOrOptions }
        : modeOrOptions ?? {};
    const tmp = `${filePath}.${process.pid}.tmp`;
    try {
        if (options.mode !== undefined) {
            (0, fs_1.writeFileSync)(tmp, JSON.stringify(data, null, 2) + '\n', {
                mode: options.mode,
            });
        }
        else {
            (0, fs_1.writeFileSync)(tmp, JSON.stringify(data, null, 2) + '\n');
        }
        (0, fs_1.renameSync)(tmp, filePath);
        if (options.mode !== undefined) {
            // Re-assert the mode on the destination — covers the case where the
            // destination already existed at a looser mode prior to this write.
            (0, fs_1.chmodSync)(filePath, options.mode);
        }
    }
    catch (err) {
        try {
            (0, fs_1.unlinkSync)(tmp);
        }
        catch {
            // Best-effort cleanup
        }
        throw err;
    }
}
