"use strict";
/* Socket Lib - Built with rolldown */
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const require_runtime = require('../_virtual/_rolldown/runtime.js');
const require_primordials_string = require('../primordials/string.js');
const require_primordials_regexp = require('../primordials/regexp.js');
const require_primordials_object = require('../primordials/object.js');
const require_env_home = require('../env/home.js');
let node_fs = require("node:fs");
let node_path = require("node:path");
node_path = require_runtime.__toESM(node_path);
let node_os = require("node:os");
let node_process = require("node:process");
node_process = require_runtime.__toESM(node_process);

//#region src/secrets/rc.ts
/**
* @file Write a managed `export VAR='<value>'` block to the user's shell rc
*   ("run commands") file. macOS only for now. `rc` is the historical Unix
*   suffix for shell-startup files (`.bashrc`, `.zshrc`, `.cshrc`) — short for
*   "run commands", a convention from MIT's CTSS (1965) carried through Multics
*   into Unix. This module writes a managed block into that file so the value
*   is exported into every subsequent shell session. Use case: `readSecret()`
*   from `./keychain` round-trips through the OS credential store on every
*   call. On macOS each call triggers a Keychain auth prompt unless the
*   keychain item's ACL allows the calling process. That's the right shape for
*   tools that read the secret once per process — but if you wire
*   `readSecret()` into a shell rc file directly, the user gets an auth prompt
*   on every new shell. Claude Code's Bash tool spawns a fresh shell per
*   command, which means continuous prompt flood. Solution: write the literal
*   value into ~/.zshenv (or equivalent) **once**, at install time, so every
*   subsequent shell session picks up the env var without re-reading the
*   keychain. The keychain is still the canonical store; this helper is just a
*   cached materialization that lives in the rc file. API: write({ service,
*   exports, notes?, legacySentinels? }) → { rcPath, outcome: 'inserted' |
*   'updated' | 'unchanged' } | undefined clear(service, legacySentinels?) →
*   boolean (true when a block was found and removed) Block layout (idempotent
*   — re-running with the same exports returns `outcome: 'unchanged'`):
*
*   # BEGIN <service> env (managed)
*
*   # Token persisted by <installer>.
*
*   # Rotate via: <rotate-command>
*
*   export VAR_1='<value>' export VAR_2='<value>'
*
*   # END <service> env (managed)
*
*   Target file by shell: zsh → ~/.zshenv (sourced by every zsh, including
*   non-interactive) bash → ~/.bashrc (or ~/.bash_profile fallback) For zsh we
*   deliberately pick .zshenv (not .zshrc) because tools that spawn
*   non-interactive shells (Claude Code, IDE plugins, CI runners) skip .zshrc
*   and would miss the export.
*/
function buildBlock(opts) {
	const begin = `# BEGIN ${opts.service} env (managed)`;
	const end = `# END ${opts.service} env (managed)`;
	const noteLines = (opts.notes ?? []).map((line) => `# ${line}`);
	const exportLines = require_primordials_object.ObjectEntries(opts.exports).map(([name, value]) => `export ${name}=${shellSingleQuote(value)}`);
	const body = [...noteLines, ...exportLines].join("\n");
	return {
		begin,
		end,
		body,
		full: `${begin}\n${body}\n${end}`
	};
}
/**
* Remove the managed block from the user's shell rc file. Used by an uninstall
* / clear flow. Returns `true` when a block was found and removed, `false` when
* no block was present.
*/
function clear(service, legacySentinels = []) {
	if ((0, node_os.platform)() !== "darwin") return false;
	const rcPath = pickRcFile();
	if (!rcPath || !(0, node_fs.existsSync)(rcPath)) return false;
	let existing = (0, node_fs.readFileSync)(rcPath, "utf8");
	let removedAny = false;
	const sentinelsToStrip = [`# BEGIN ${service} env (managed)`, ...legacySentinels];
	for (const begin of sentinelsToStrip) {
		const end = begin.replace(/\bBEGIN\b/, "END");
		const endStripped = end.replace(/\s*\(managed\)\s*$/, "");
		const endAlt = end === endStripped ? escapeRegExp(end) : `(?:${escapeRegExp(end)}|${escapeRegExp(endStripped)})`;
		const re = new require_primordials_regexp.RegExpCtor(`\n*${escapeRegExp(begin)}[\\s\\S]*?${endAlt}\n?`, "g");
		const next = existing.replace(re, "\n");
		if (next !== existing) {
			removedAny = true;
			existing = next;
		}
	}
	if (removedAny) writeRcFile(rcPath, existing.replace(/\n{3,}/g, "\n\n"));
	return removedAny;
}
function escapeRegExp(s) {
	return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function pickRcFile(shellOverride) {
	const home = /* @__PURE__ */ require_env_home.getHome();
	if (!home) return;
	const shellPath = node_process.default.env["SHELL"] ?? "";
	const shell = shellOverride ?? (require_primordials_string.StringPrototypeEndsWith(shellPath, "zsh") ? "zsh" : require_primordials_string.StringPrototypeEndsWith(shellPath, "bash") ? "bash" : require_primordials_string.StringPrototypeEndsWith(shellPath, "fish") ? "fish" : void 0);
	if (shell === "zsh") return node_path.default.join(home, ".zshenv");
	if (shell === "bash") {
		const bashrc = node_path.default.join(home, ".bashrc");
		if ((0, node_fs.existsSync)(bashrc)) return bashrc;
		const bashProfile = node_path.default.join(home, ".bash_profile");
		if ((0, node_fs.existsSync)(bashProfile)) return bashProfile;
		return bashrc;
	}
	if (shell === "fish") return node_path.default.join(home, ".config", "fish", "config.fish");
}
function shellSingleQuote(value) {
	return `'${value.replace(/'/g, "'\\''")}'`;
}
/**
* Insert or update the managed env-var block in the user's shell run-commands
* file (`~/.zshenv` for zsh, `~/.bashrc` / `~/.bash_profile` for bash,
* `~/.config/fish/config.fish` for fish). macOS only — Linux + Windows return
* `{outcome: 'skipped', reason: 'unsupported-platform'}` so callers can fall
* back to a copy- pasteable instruction without special-casing an `undefined`
* return.
*
* The block is matched by BEGIN/END sentinels, so it coexists with other
* managed blocks (homebrew, nvm, etc.). Idempotent: re-running with the same
* exports produces `outcome: 'unchanged'` and doesn't touch the file.
*
* `legacySentinels` lets a consumer migrate the block from an older BEGIN
* string. Each legacy block (matched by `BEGIN <legacy>` → `END <legacy>`) is
* stripped before the new block is written.
*
* `shell` and `rcPath` override the auto-detected target — useful for chezmoi /
* dotfile-manager users or installers running under a non-default shell.
*/
function write(opts) {
	if ((0, node_os.platform)() !== "darwin") return {
		rcPath: void 0,
		outcome: "skipped",
		reason: "unsupported-platform"
	};
	const rcPath = opts.rcPath ?? pickRcFile(opts.shell);
	if (!rcPath) return {
		rcPath: void 0,
		outcome: "skipped",
		reason: "unknown-shell"
	};
	const { begin, end, full: desiredBlock } = buildBlock(opts);
	let onDisk = "";
	if ((0, node_fs.existsSync)(rcPath)) onDisk = (0, node_fs.readFileSync)(rcPath, "utf8");
	let working = onDisk;
	for (const legacyBegin of opts.legacySentinels ?? []) {
		const legacyEnd = legacyBegin.replace(/\bBEGIN\b/, "END");
		const legacyEndStripped = legacyEnd.replace(/\s*\(managed\)\s*$/, "");
		const endAlt = legacyEnd === legacyEndStripped ? escapeRegExp(legacyEnd) : `(?:${escapeRegExp(legacyEnd)}|${escapeRegExp(legacyEndStripped)})`;
		const legacyRe = new require_primordials_regexp.RegExpCtor(`\n*${escapeRegExp(legacyBegin)}[\\s\\S]*?${endAlt}\n?`, "g");
		working = working.replace(legacyRe, "\n");
	}
	const match = new require_primordials_regexp.RegExpCtor(`${escapeRegExp(begin)}[\\s\\S]*?${escapeRegExp(end)}`).exec(working);
	if (match) {
		if (match[0] === desiredBlock && working === onDisk) return {
			rcPath,
			outcome: "unchanged"
		};
		writeRcFile(rcPath, (working.slice(0, match.index) + desiredBlock + working.slice(match.index + match[0].length)).replace(/\n{3,}/g, "\n\n"));
		return {
			rcPath,
			outcome: "updated"
		};
	}
	const prefix = working.length > 0 && !require_primordials_string.StringPrototypeEndsWith(working, "\n\n") ? require_primordials_string.StringPrototypeEndsWith(working, "\n") ? "\n" : "\n\n" : "";
	writeRcFile(rcPath, `${working}${prefix}${desiredBlock}\n`.replace(/\n{3,}/g, "\n\n"));
	return {
		rcPath,
		outcome: "inserted"
	};
}
/**
* Internal: write an rc file with 0o600 (owner-only). The rc file embeds a
* literal SOCKET_API_KEY value so the shell rc can `export` it on session start
* without re-prompting the keychain. The file must NEVER be readable by other
* local users — `writeFileSync` with no `mode:` lands at `0o644` on first
* create (default umask 022), exposing the token on multi-user macOS / Linux
* machines. We unconditionally chmod after write so existing files with looser
* permissions also get tightened.
*/
function writeRcFile(rcPath, contents) {
	(0, node_fs.writeFileSync)(rcPath, contents, { mode: 384 });
	try {
		(0, node_fs.chmodSync)(rcPath, 384);
	} catch {}
}

//#endregion
exports.buildBlock = buildBlock;
exports.clear = clear;
exports.escapeRegExp = escapeRegExp;
exports.pickRcFile = pickRcFile;
exports.shellSingleQuote = shellSingleQuote;
exports.write = write;
exports.writeRcFile = writeRcFile;