"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_error = require('../primordials/error.js');
const require_primordials_json = require('../primordials/json.js');
const require_primordials_promise = require('../primordials/promise.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);
let node_child_process = require("node:child_process");

//#region src/secrets/windows.ts
/**
* @file Windows backend via PowerShell CredentialManager module, with a
*   DPAPI-encrypted file fallback. Two paths, tried in order:
*
*   1. CredentialManager PowerShell module (`New-StoredCredential` /
*      `Get-StoredCredential` / `Remove-StoredCredential`). The cleanest path —
*      stored credentials live in the Windows Credential Manager, the same
*      place `cmdkey` writes to. Requires the module to be installed
*      (`Install-Module CredentialManager -Scope CurrentUser`).
*   2. DPAPI-encrypted file under `%APPDATA%\<service>\<account>.enc`. Used when
*      the CredentialManager module isn't available.
*      `System.Security.Cryptography.ProtectedData` encrypts under the
*      current-user machine key — readable only by this user on this machine,
*      never plaintext. The target name composed for CredentialManager is
*      `service:account` (matching `cmdkey /generic:<target>` convention).
*/
const POWERSHELL_BIN = "powershell";
function buildTarget(service, account) {
	return `${service}:${account}`;
}
async function deleteWindows(service, account) {
	const target = buildTarget(service, account);
	let removedAny = false;
	if ((await runPsAsync(`
    try { Remove-StoredCredential -Target ${quotePs(target)}; exit 0 }
    catch { exit 1 }
  `)).status === 0) removedAny = true;
	const filePath = getDpapiFilePath(service, account);
	if ((0, node_fs.existsSync)(filePath)) try {
		const { rmSync } = await import("node:fs");
		rmSync(filePath, { force: true });
		removedAny = true;
	} catch {}
	return removedAny ? "removed" : "absent";
}
function deleteWindowsSync(service, account) {
	const target = buildTarget(service, account);
	let removedAny = false;
	if (runPsSync(`
    try { Remove-StoredCredential -Target ${quotePs(target)}; exit 0 }
    catch { exit 1 }
  `).status === 0) removedAny = true;
	const filePath = getDpapiFilePath(service, account);
	if ((0, node_fs.existsSync)(filePath)) try {
		require("node:fs").rmSync(filePath, { force: true });
		removedAny = true;
	} catch {}
	return removedAny ? "removed" : "absent";
}
function getDpapiFilePath(service, account) {
	validateKeychainComponent(service, "service");
	validateKeychainComponent(account, "account");
	const appData = node_process.default.env["APPDATA"] ?? node_path.default.join((0, node_os.homedir)(), "AppData", "Roaming");
	return node_path.default.join(appData, service, `${account}.enc`);
}
function isWindowsBackendAvailable() {
	return (0, node_child_process.spawnSync)(POWERSHELL_BIN, [
		"-NoProfile",
		"-Command",
		"exit 0"
	], { stdio: "ignore" }).status === 0;
}
function quotePs(value) {
	return `'${value.replace(/'/g, "''")}'`;
}
async function readDpapi(filePath) {
	if (!(0, node_fs.existsSync)(filePath)) return;
	const r = await runPsAsync(`
    Add-Type -AssemblyName System.Security
    $bytes = [Convert]::FromBase64String((Get-Content -Raw ${quotePs(filePath)}))
    $plain = [System.Security.Cryptography.ProtectedData]::Unprotect($bytes, $null, 'CurrentUser')
    [System.Text.Encoding]::UTF8.GetString($plain)
  `);
	if (r.status !== 0) return;
	return r.stdout.trim() || void 0;
}
function readDpapiSync(filePath) {
	if (!(0, node_fs.existsSync)(filePath)) return;
	const r = runPsSync(`
    Add-Type -AssemblyName System.Security
    $bytes = [Convert]::FromBase64String((Get-Content -Raw ${quotePs(filePath)}))
    $plain = [System.Security.Cryptography.ProtectedData]::Unprotect($bytes, $null, 'CurrentUser')
    [System.Text.Encoding]::UTF8.GetString($plain)
  `);
	if (r.status !== 0) return;
	return r.stdout.trim() || void 0;
}
async function readWindows(service, account) {
	const ps = await runPsAsync(`
    try {
      (Get-StoredCredential -Target ${quotePs(buildTarget(service, account))}).Password |
        ConvertFrom-SecureString -AsPlainText
    } catch { exit 1 }
  `);
	if (ps.status === 0) {
		const out = ps.stdout.trim();
		if (out) return out;
	}
	return readDpapi(getDpapiFilePath(service, account));
}
function readWindowsSync(service, account) {
	const ps = runPsSync(`
    try {
      (Get-StoredCredential -Target ${quotePs(buildTarget(service, account))}).Password |
        ConvertFrom-SecureString -AsPlainText
    } catch { exit 1 }
  `);
	if (ps.status === 0) {
		const out = ps.stdout.trim();
		if (out) return out;
	}
	return readDpapiSync(getDpapiFilePath(service, account));
}
function runPsAsync(script, input) {
	return new require_primordials_promise.PromiseCtor((resolve) => {
		const child = (0, node_child_process.spawn)(POWERSHELL_BIN, [
			"-NoProfile",
			"-Command",
			script
		], { stdio: [
			"pipe",
			"pipe",
			"pipe"
		] });
		let stdout = "";
		let stderr = "";
		child.stdout.setEncoding("utf8");
		child.stdout.on("data", (chunk) => {
			stdout += chunk;
		});
		child.stderr.setEncoding("utf8");
		child.stderr.on("data", (chunk) => {
			stderr += chunk;
		});
		child.on("error", () => resolve({
			status: -1,
			stdout,
			stderr
		}));
		child.on("close", (status) => resolve({
			status,
			stdout,
			stderr
		}));
		if (input !== void 0) child.stdin.end(input);
		else child.stdin.end();
	});
}
function runPsSync(script, input) {
	const r = (0, node_child_process.spawnSync)(POWERSHELL_BIN, [
		"-NoProfile",
		"-Command",
		script
	], {
		encoding: "utf8",
		input,
		stdio: [
			"pipe",
			"pipe",
			"pipe"
		]
	});
	return {
		status: r.status,
		stdout: r.stdout,
		stderr: r.stderr
	};
}
/**
* Reject identifier components (service / account names) that contain path
* separators, `..` segments, or NUL bytes. These would escape the intended
* `%APPDATA%\<service>\<account>.enc` layout and let a caller read or overwrite
* arbitrary files under the user's profile.
*
* Throws on bad input rather than sanitizing — callers should pass logical
* identifiers (e.g. `socket-cli`, `SOCKET_API_KEY`), not paths.
*/
function validateKeychainComponent(value, name) {
	if (/[\\/]/.test(value) || value.includes("..") || value.includes("\0") || value === "" || value === ".") throw new require_primordials_error.ErrorCtor(`secrets/windows: ${name} contains path-traversal characters: ${require_primordials_json.JSONStringify(value)}. Use a plain identifier (no \\\\, /, .., or NUL).`);
}
async function writeDpapi(filePath, value) {
	const dir = node_path.default.dirname(filePath);
	if (!(0, node_fs.existsSync)(dir)) (0, node_fs.mkdirSync)(dir, { recursive: true });
	const r = await runPsAsync(`
    Add-Type -AssemblyName System.Security
    $token = [Console]::In.ReadToEnd().Trim()
    $bytes = [System.Text.Encoding]::UTF8.GetBytes($token)
    $protected = [System.Security.Cryptography.ProtectedData]::Protect($bytes, $null, 'CurrentUser')
    [Convert]::ToBase64String($protected) | Set-Content -Path ${quotePs(filePath)} -NoNewline
  `, value);
	if (r.status !== 0) throw new require_primordials_error.ErrorCtor(`DPAPI file write failed: ${r.stderr.trim()}. Install the CredentialManager PowerShell module (\`Install-Module CredentialManager -Scope CurrentUser\`) for a cleaner storage path.`);
}
function writeDpapiSync(filePath, value) {
	const dir = node_path.default.dirname(filePath);
	if (!(0, node_fs.existsSync)(dir)) (0, node_fs.mkdirSync)(dir, { recursive: true });
	const r = runPsSync(`
    Add-Type -AssemblyName System.Security
    $token = [Console]::In.ReadToEnd().Trim()
    $bytes = [System.Text.Encoding]::UTF8.GetBytes($token)
    $protected = [System.Security.Cryptography.ProtectedData]::Protect($bytes, $null, 'CurrentUser')
    [Convert]::ToBase64String($protected) | Set-Content -Path ${quotePs(filePath)} -NoNewline
  `, value);
	if (r.status !== 0) throw new require_primordials_error.ErrorCtor(`DPAPI file write failed: ${r.stderr.trim()}. Install the CredentialManager PowerShell module (\`Install-Module CredentialManager -Scope CurrentUser\`) for a cleaner storage path.`);
}
async function writeWindows(service, account, value, _label) {
	if ((await runPsAsync(`
    $token = $input | Out-String
    $token = $token.Trim()
    $secure = ConvertTo-SecureString $token -AsPlainText -Force
    try {
      New-StoredCredential -Target ${quotePs(buildTarget(service, account))} -UserName ${quotePs(account)} -SecurePassword $secure -Persist LocalMachine | Out-Null
      exit 0
    } catch { exit 1 }
  `, value)).status === 0) return;
	await writeDpapi(getDpapiFilePath(service, account), value);
}
function writeWindowsSync(service, account, value, _label) {
	if (runPsSync(`
    $token = $input | Out-String
    $token = $token.Trim()
    $secure = ConvertTo-SecureString $token -AsPlainText -Force
    try {
      New-StoredCredential -Target ${quotePs(buildTarget(service, account))} -UserName ${quotePs(account)} -SecurePassword $secure -Persist LocalMachine | Out-Null
      exit 0
    } catch { exit 1 }
  `, value).status === 0) return;
	writeDpapiSync(getDpapiFilePath(service, account), value);
}

//#endregion
exports.buildTarget = buildTarget;
exports.deleteWindows = deleteWindows;
exports.deleteWindowsSync = deleteWindowsSync;
exports.getDpapiFilePath = getDpapiFilePath;
exports.isWindowsBackendAvailable = isWindowsBackendAvailable;
exports.quotePs = quotePs;
exports.readDpapi = readDpapi;
exports.readDpapiSync = readDpapiSync;
exports.readWindows = readWindows;
exports.readWindowsSync = readWindowsSync;
exports.runPsAsync = runPsAsync;
exports.runPsSync = runPsSync;
exports.validateKeychainComponent = validateKeychainComponent;
exports.writeDpapi = writeDpapi;
exports.writeDpapiSync = writeDpapiSync;
exports.writeWindows = writeWindows;
exports.writeWindowsSync = writeWindowsSync;