import { ak as join, p as networkFetch, h as getDefaultNetworkController, ay as dirname } from "./fetch-virtual-server-BZi6n2Qk.js";
const DEFAULT_NEON_API_HOST = "https://console.neon.tech/api/v2";
const DEFAULT_NEON_OAUTH_HOST = "https://oauth2.neon.tech";
const DEFAULT_NEON_CLIENT_ID = "neonctl";
const NEON_CREDENTIALS_PATH = "/home/user/.config/neonctl/credentials.json";
const NEON_PENDING_AUTH_PATH = "/home/user/.config/neonctl/pending-auth.json";
const NEON_CALLBACK_REDIRECT_URI = "http://127.0.0.1:44555/callback";
const ALWAYS_PRESENT_SCOPES = ["openid", "offline", "offline_access"];
const NEON_SCOPES = [
  ...ALWAYS_PRESENT_SCOPES,
  "urn:neoncloud:projects:create",
  "urn:neoncloud:projects:read",
  "urn:neoncloud:projects:update",
  "urn:neoncloud:projects:delete",
  "urn:neoncloud:orgs:create",
  "urn:neoncloud:orgs:read",
  "urn:neoncloud:orgs:update",
  "urn:neoncloud:orgs:delete",
  "urn:neoncloud:orgs:permission"
];
function normalizeLineEndings(value) {
  return value.replace(/\r\n/g, "\n");
}
function ensureParentDir(vfs, filePath) {
  const parent = dirname(filePath);
  if (!vfs.existsSync(parent)) {
    vfs.mkdirSync(parent, { recursive: true });
  }
}
function base64UrlEncode(bytes) {
  if (typeof Buffer !== "undefined") {
    return Buffer.from(bytes).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
  }
  let binary = "";
  for (let index = 0; index < bytes.length; index += 1) {
    binary += String.fromCharCode(bytes[index]);
  }
  return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
}
function randomBytes(length) {
  const bytes = new Uint8Array(length);
  crypto.getRandomValues(bytes);
  return bytes;
}
function parseJwtPayload(token) {
  if (!token) {
    return null;
  }
  const parts = token.split(".");
  if (parts.length < 2) {
    return null;
  }
  try {
    const segment = parts[1].replace(/-/g, "+").replace(/_/g, "/").padEnd(Math.ceil(parts[1].length / 4) * 4, "=");
    const decoded = typeof Buffer !== "undefined" ? Buffer.from(segment, "base64").toString("utf8") : atob(segment);
    return JSON.parse(decoded);
  } catch {
    return null;
  }
}
function normalizeNeonCredentials(value) {
  if (!value || typeof value !== "object") {
    return null;
  }
  const record = value;
  const credentials = {};
  if (typeof record.access_token === "string" && record.access_token.trim()) {
    credentials.access_token = record.access_token.trim();
  }
  if (typeof record.refresh_token === "string" && record.refresh_token.trim()) {
    credentials.refresh_token = record.refresh_token.trim();
  }
  if (typeof record.token_type === "string" && record.token_type.trim()) {
    credentials.token_type = record.token_type.trim();
  }
  if (typeof record.scope === "string" && record.scope.trim()) {
    credentials.scope = record.scope.trim();
  }
  if (typeof record.id_token === "string" && record.id_token.trim()) {
    credentials.id_token = record.id_token.trim();
  }
  if (typeof record.user_id === "string" && record.user_id.trim()) {
    credentials.user_id = record.user_id.trim();
  }
  if (typeof record.expires_in === "number" && Number.isFinite(record.expires_in)) {
    credentials.expires_in = record.expires_in;
  }
  if (typeof record.expires_at === "number" && Number.isFinite(record.expires_at)) {
    credentials.expires_at = record.expires_at;
  }
  if (typeof record.personal_api_key === "string" && record.personal_api_key.trim()) {
    credentials.personal_api_key = record.personal_api_key.trim();
  }
  if (typeof record.personal_api_key_id === "string" && record.personal_api_key_id.trim() || typeof record.personal_api_key_id === "number") {
    credentials.personal_api_key_id = String(record.personal_api_key_id).trim();
  }
  if (typeof record.personal_api_key_name === "string" && record.personal_api_key_name.trim()) {
    credentials.personal_api_key_name = record.personal_api_key_name.trim();
  }
  return credentials.access_token || credentials.refresh_token ? credentials : null;
}
function normalizePendingAuthState(value) {
  if (!value || typeof value !== "object") {
    return null;
  }
  const record = value;
  const state = typeof record.state === "string" ? record.state.trim() : "";
  const codeVerifier = typeof record.code_verifier === "string" ? record.code_verifier.trim() : typeof record.codeVerifier === "string" ? record.codeVerifier.trim() : "";
  if (!state || !codeVerifier) {
    return null;
  }
  const pendingState = {
    state,
    code_verifier: codeVerifier
  };
  if (typeof record.oauth_host === "string" && record.oauth_host.trim()) {
    pendingState.oauth_host = record.oauth_host.trim();
  }
  if (typeof record.client_id === "string" && record.client_id.trim()) {
    pendingState.client_id = record.client_id.trim();
  }
  if (typeof record.redirect_uri === "string" && record.redirect_uri.trim()) {
    pendingState.redirect_uri = record.redirect_uri.trim();
  }
  if (typeof record.created_at === "number" && Number.isFinite(record.created_at)) {
    pendingState.created_at = record.created_at;
  }
  return pendingState;
}
function inferUserId(credentials) {
  const payload = parseJwtPayload(credentials.id_token);
  return typeof (payload == null ? void 0 : payload.sub) === "string" && payload.sub.trim() ? payload.sub.trim() : credentials.user_id;
}
function extendTokenSet(tokenSet, previous) {
  var _a, _b, _c, _d, _e;
  const expiresIn = typeof tokenSet.expires_in === "number" ? tokenSet.expires_in : 0;
  const credentials = {
    access_token: ((_a = tokenSet.access_token) == null ? void 0 : _a.trim()) || (previous == null ? void 0 : previous.access_token),
    refresh_token: ((_b = tokenSet.refresh_token) == null ? void 0 : _b.trim()) || (previous == null ? void 0 : previous.refresh_token),
    token_type: ((_c = tokenSet.token_type) == null ? void 0 : _c.trim()) || (previous == null ? void 0 : previous.token_type),
    scope: ((_d = tokenSet.scope) == null ? void 0 : _d.trim()) || (previous == null ? void 0 : previous.scope),
    expires_in: expiresIn || (previous == null ? void 0 : previous.expires_in),
    expires_at: Date.now() + expiresIn * 1e3,
    id_token: ((_e = tokenSet.id_token) == null ? void 0 : _e.trim()) || (previous == null ? void 0 : previous.id_token),
    personal_api_key: previous == null ? void 0 : previous.personal_api_key,
    personal_api_key_id: previous == null ? void 0 : previous.personal_api_key_id,
    personal_api_key_name: previous == null ? void 0 : previous.personal_api_key_name
  };
  credentials.user_id = inferUserId(credentials);
  return credentials;
}
async function neonFetch(url, init = {}) {
  return networkFetch(url, init, getDefaultNetworkController());
}
async function postTokenRequest(oauthHost, body) {
  const response = await neonFetch(`${normalizeNeonOauthHost(oauthHost)}/oauth2/token`, {
    method: "POST",
    headers: {
      "content-type": "application/x-www-form-urlencoded",
      accept: "application/json"
    },
    body: body.toString()
  });
  const text = await response.text();
  let parsed = null;
  try {
    parsed = text ? JSON.parse(text) : {};
  } catch {
    parsed = null;
  }
  if (!response.ok) {
    const detail = (parsed == null ? void 0 : parsed.error_description) || (parsed == null ? void 0 : parsed.error) || text || `${response.status} ${response.statusText}`;
    throw new Error(`Neon token request failed: ${detail}`);
  }
  if (!(parsed == null ? void 0 : parsed.access_token)) {
    throw new Error("Neon token request did not return an access token.");
  }
  return parsed;
}
function getJsonObject(value) {
  if (!value.trim()) {
    return null;
  }
  try {
    const parsed = JSON.parse(value);
    return parsed && typeof parsed === "object" ? parsed : null;
  } catch {
    return null;
  }
}
function extractNeonApiKey(response) {
  const nested = response.api_key && typeof response.api_key === "object" ? response.api_key : null;
  const key = typeof response.key === "string" && response.key.trim() ? response.key.trim() : typeof (nested == null ? void 0 : nested.key) === "string" && nested.key.trim() ? nested.key.trim() : null;
  const name = typeof response.name === "string" && response.name.trim() ? response.name.trim() : typeof response.key_name === "string" && response.key_name.trim() ? response.key_name.trim() : typeof (nested == null ? void 0 : nested.name) === "string" && nested.name.trim() ? nested.name.trim() : typeof (nested == null ? void 0 : nested.key_name) === "string" && nested.key_name.trim() ? nested.key_name.trim() : null;
  const idValue = typeof response.id === "string" || typeof response.id === "number" ? response.id : typeof (nested == null ? void 0 : nested.id) === "string" || typeof (nested == null ? void 0 : nested.id) === "number" ? nested.id : null;
  return { id: idValue, key, name };
}
function normalizeNeonApiHost(value) {
  const trimmed = value == null ? void 0 : value.trim();
  if (!trimmed) {
    return DEFAULT_NEON_API_HOST;
  }
  return trimmed.replace(/\/+$/g, "") || DEFAULT_NEON_API_HOST;
}
function normalizeNeonOauthHost(value) {
  const trimmed = value == null ? void 0 : value.trim();
  if (!trimmed) {
    return DEFAULT_NEON_OAUTH_HOST;
  }
  return trimmed.replace(/\/+$/g, "") || DEFAULT_NEON_OAUTH_HOST;
}
function readNeonCredentials(vfs, filePath = NEON_CREDENTIALS_PATH) {
  if (!vfs.existsSync(filePath)) {
    return null;
  }
  try {
    const content = normalizeLineEndings(vfs.readFileSync(filePath, "utf8"));
    return normalizeNeonCredentials(JSON.parse(content));
  } catch {
    return null;
  }
}
function readPendingNeonAuthState(vfs, filePath = NEON_PENDING_AUTH_PATH) {
  if (!vfs.existsSync(filePath)) {
    return null;
  }
  try {
    const content = normalizeLineEndings(vfs.readFileSync(filePath, "utf8"));
    return normalizePendingAuthState(JSON.parse(content));
  } catch {
    return null;
  }
}
function writeNeonCredentials(vfs, credentials, filePath = NEON_CREDENTIALS_PATH) {
  const normalized = normalizeNeonCredentials(credentials);
  if (!normalized) {
    throw new Error("Cannot write empty Neon credentials.");
  }
  ensureParentDir(vfs, filePath);
  vfs.writeFileSync(filePath, JSON.stringify(normalized, null, 2) + "\n");
}
function writePendingNeonAuthState(vfs, state, filePath = NEON_PENDING_AUTH_PATH) {
  const normalized = normalizePendingAuthState(state);
  if (!normalized) {
    throw new Error("Cannot write empty Neon pending auth state.");
  }
  ensureParentDir(vfs, filePath);
  vfs.writeFileSync(filePath, JSON.stringify(normalized, null, 2) + "\n");
}
function deleteNeonCredentials(vfs, filePath = NEON_CREDENTIALS_PATH) {
  if (!vfs.existsSync(filePath)) {
    return false;
  }
  try {
    vfs.unlinkSync(filePath);
    return true;
  } catch {
    return false;
  }
}
function deletePendingNeonAuthState(vfs, filePath = NEON_PENDING_AUTH_PATH) {
  if (!vfs.existsSync(filePath)) {
    return false;
  }
  try {
    vfs.unlinkSync(filePath);
    return true;
  } catch {
    return false;
  }
}
function getNeonIdentityLabel(credentials) {
  if (!credentials) {
    return null;
  }
  const payload = parseJwtPayload(credentials.id_token);
  const email = typeof (payload == null ? void 0 : payload.email) === "string" && payload.email.trim() ? payload.email.trim() : null;
  if (email) {
    return email;
  }
  const userId = inferUserId(credentials);
  return (userId == null ? void 0 : userId.trim()) ? userId.trim() : null;
}
function getDefaultNeonConfigDir(env) {
  var _a, _b;
  const xdgConfigHome = (_a = env == null ? void 0 : env.XDG_CONFIG_HOME) == null ? void 0 : _a.trim();
  if (xdgConfigHome) {
    return join(xdgConfigHome, "neonctl");
  }
  const home = ((_b = env == null ? void 0 : env.HOME) == null ? void 0 : _b.trim()) || "/home/user";
  return join(home, ".config", "neonctl");
}
function getNeonCredentialsPath(configDir) {
  return join(configDir, "credentials.json");
}
function getNeonPendingAuthPath(configDir) {
  return join(configDir, "pending-auth.json");
}
function buildNeonAuthorizationUrl(options) {
  const params = new URLSearchParams({
    client_id: (options.clientId || DEFAULT_NEON_CLIENT_ID).trim() || DEFAULT_NEON_CLIENT_ID,
    response_type: "code",
    scope: NEON_SCOPES.join(" "),
    state: options.state,
    code_challenge: options.codeChallenge,
    code_challenge_method: "S256",
    redirect_uri: options.redirectUri || NEON_CALLBACK_REDIRECT_URI
  });
  return `${normalizeNeonOauthHost(options.oauthHost)}/oauth2/auth?${params.toString()}`;
}
async function createNeonPkcePair() {
  const codeVerifier = base64UrlEncode(randomBytes(48));
  const state = base64UrlEncode(randomBytes(24));
  const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(codeVerifier));
  const codeChallenge = base64UrlEncode(new Uint8Array(digest));
  return { codeVerifier, codeChallenge, state };
}
async function exchangeNeonAuthorizationCode(options) {
  const body = new URLSearchParams({
    grant_type: "authorization_code",
    client_id: (options.clientId || DEFAULT_NEON_CLIENT_ID).trim() || DEFAULT_NEON_CLIENT_ID,
    code: options.code,
    code_verifier: options.codeVerifier,
    redirect_uri: options.redirectUri
  });
  const tokenSet = await postTokenRequest(options.oauthHost || DEFAULT_NEON_OAUTH_HOST, body);
  return extendTokenSet(tokenSet);
}
async function refreshNeonCredentials(credentials, options) {
  if (!credentials.refresh_token) {
    throw new Error("Saved Neon credentials do not include a refresh token.");
  }
  const body = new URLSearchParams({
    grant_type: "refresh_token",
    client_id: ((options == null ? void 0 : options.clientId) || DEFAULT_NEON_CLIENT_ID).trim() || DEFAULT_NEON_CLIENT_ID,
    refresh_token: credentials.refresh_token
  });
  const tokenSet = await postTokenRequest((options == null ? void 0 : options.oauthHost) || DEFAULT_NEON_OAUTH_HOST, body);
  return extendTokenSet(tokenSet, credentials);
}
const DEFAULT_NEON_PERSONAL_API_KEY_PREFIX = "almostnode-webide";
function buildDefaultNeonApiKeyName(now = /* @__PURE__ */ new Date()) {
  const stamp = now.toISOString().replace(/[-:]/g, "").replace(/\.\d+Z$/, "Z");
  return `${DEFAULT_NEON_PERSONAL_API_KEY_PREFIX}-${stamp}`;
}
async function deleteNeonApiKey(accessToken, keyId, options) {
  const trimmedId = keyId.trim();
  if (!trimmedId) return false;
  const response = await neonFetch(
    `${normalizeNeonApiHost(options == null ? void 0 : options.apiHost)}/api_keys/${encodeURIComponent(trimmedId)}`,
    {
      method: "DELETE",
      headers: {
        accept: "application/json",
        authorization: `Bearer ${accessToken}`
      }
    }
  );
  if (response.ok) return true;
  if (response.status === 404) return false;
  const text = await response.text().catch(() => "");
  const parsed = getJsonObject(text);
  const detail = typeof (parsed == null ? void 0 : parsed.message) === "string" && parsed.message.trim() || typeof (parsed == null ? void 0 : parsed.error) === "string" && parsed.error.trim() || text || `${response.status} ${response.statusText}`;
  throw new Error(`Neon API key deletion failed: ${detail}`);
}
async function createNeonApiKey(accessToken, options) {
  const keyName = options.keyName.trim();
  if (!keyName) {
    throw new Error("A Neon API key name is required.");
  }
  const response = await neonFetch(`${normalizeNeonApiHost(options.apiHost)}/api_keys`, {
    method: "POST",
    headers: {
      accept: "application/json",
      authorization: `Bearer ${accessToken}`,
      "content-type": "application/json"
    },
    body: JSON.stringify({ key_name: keyName })
  });
  const text = await response.text();
  const parsed = getJsonObject(text);
  if (!response.ok) {
    const detail = typeof (parsed == null ? void 0 : parsed.message) === "string" && parsed.message.trim() || typeof (parsed == null ? void 0 : parsed.error) === "string" && parsed.error.trim() || text || `${response.status} ${response.statusText}`;
    throw new Error(`Neon API key creation failed: ${detail}`);
  }
  const created = extractNeonApiKey(parsed || {});
  if (!created.key) {
    throw new Error("Neon API key creation succeeded but no key token was returned.");
  }
  return {
    id: created.id,
    key: created.key,
    name: created.name || keyName
  };
}
function ok(stdout) {
  return { stdout, stderr: "", exitCode: 0 };
}
function err(stderr, exitCode = 1) {
  return { stdout: "", stderr, exitCode };
}
function envToRecord(env) {
  if (!env) {
    return {};
  }
  if (env instanceof Map) {
    return Object.fromEntries(env);
  }
  return env;
}
function signalAborted(signal) {
  return (signal == null ? void 0 : signal.aborted) === true;
}
function abortResult() {
  return err("neon: command aborted\n", 130);
}
function formatErrorMessage(error) {
  return error instanceof Error ? error.message : String(error);
}
const DESKTOP_OAUTH_LOOPBACK_BRIDGE_KEY = Symbol.for(
  "almostnode.desktopOAuthLoopback"
);
const DESKTOP_NEON_SUCCESS_HTML = `<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Neon authentication complete</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style>
      body {
        margin: 0;
        min-height: 100vh;
        display: grid;
        place-items: center;
        background: #0f172a;
        color: #e2e8f0;
        font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
      }
      main {
        max-width: 32rem;
        padding: 2rem;
        text-align: center;
      }
      h1 {
        margin: 0 0 0.75rem;
        font-size: 1.5rem;
      }
      p {
        margin: 0;
        color: #cbd5e1;
      }
    </style>
  </head>
  <body>
    <main>
      <h1>Neon authentication complete</h1>
      <p>You can close this window and return to almostnode.</p>
    </main>
  </body>
</html>`;
const NEON_DESKTOP_AUTH_TIMEOUT_MS = 18e4;
function getDesktopOAuthLoopbackBridge() {
  const candidate = globalThis[DESKTOP_OAUTH_LOOPBACK_BRIDGE_KEY];
  if (!candidate) {
    return null;
  }
  if (typeof candidate.createSession !== "function" || typeof candidate.openExternal !== "function" || typeof candidate.waitForCallback !== "function") {
    return null;
  }
  return candidate;
}
async function persistKeychainState(keychain) {
  await (keychain == null ? void 0 : keychain.persistCurrentState().catch(() => {
  }));
}
function parseCommonFlags(args) {
  const options = {};
  let index = 0;
  while (index < args.length) {
    const arg = args[index];
    const next = args[index + 1];
    if (arg === "--config-dir") {
      if (!next) return { options, rest: [], error: "missing value for --config-dir" };
      options.configDir = next;
      index += 2;
      continue;
    }
    if (arg.startsWith("--config-dir=")) {
      options.configDir = arg.slice("--config-dir=".length);
      index += 1;
      continue;
    }
    if (arg === "--api-host") {
      if (!next) return { options, rest: [], error: "missing value for --api-host" };
      options.apiHost = next;
      index += 2;
      continue;
    }
    if (arg.startsWith("--api-host=")) {
      options.apiHost = arg.slice("--api-host=".length);
      index += 1;
      continue;
    }
    if (arg === "--oauth-host") {
      if (!next) return { options, rest: [], error: "missing value for --oauth-host" };
      options.oauthHost = next;
      index += 2;
      continue;
    }
    if (arg.startsWith("--oauth-host=")) {
      options.oauthHost = arg.slice("--oauth-host=".length);
      index += 1;
      continue;
    }
    if (arg === "--client-id") {
      if (!next) return { options, rest: [], error: "missing value for --client-id" };
      options.clientId = next;
      index += 2;
      continue;
    }
    if (arg.startsWith("--client-id=")) {
      options.clientId = arg.slice("--client-id=".length);
      index += 1;
      continue;
    }
    if (arg === "--api-key") {
      if (!next) return { options, rest: [], error: "missing value for --api-key" };
      options.apiKey = next;
      index += 2;
      continue;
    }
    if (arg.startsWith("--api-key=")) {
      options.apiKey = arg.slice("--api-key=".length);
      index += 1;
      continue;
    }
    break;
  }
  return { options, rest: args.slice(index) };
}
function resolveCommonOptions(args, ctx) {
  var _a, _b, _c, _d, _e;
  const parsed = parseCommonFlags(args);
  const env = envToRecord(ctx.env);
  const configDir = ((_a = parsed.options.configDir) == null ? void 0 : _a.trim()) || getDefaultNeonConfigDir(env);
  return {
    configDir,
    credentialsPath: getNeonCredentialsPath(configDir),
    pendingAuthPath: getNeonPendingAuthPath(configDir),
    apiHost: normalizeNeonApiHost(parsed.options.apiHost || env.NEON_API_HOST),
    oauthHost: normalizeNeonOauthHost(parsed.options.oauthHost || env.NEON_OAUTH_HOST),
    clientId: ((_b = parsed.options.clientId) == null ? void 0 : _b.trim()) || ((_c = env.NEON_CLIENT_ID) == null ? void 0 : _c.trim()) || DEFAULT_NEON_CLIENT_ID,
    apiKey: ((_d = parsed.options.apiKey) == null ? void 0 : _d.trim()) || ((_e = env.NEON_API_KEY) == null ? void 0 : _e.trim()) || null,
    rest: parsed.rest,
    error: parsed.error
  };
}
function parseCallbackUrl(rawInput, expectedState) {
  const trimmed = rawInput.trim();
  let parsed;
  try {
    parsed = new URL(trimmed);
  } catch {
    if (trimmed.startsWith("/")) {
      parsed = new URL(trimmed, NEON_CALLBACK_REDIRECT_URI);
    } else if (trimmed.startsWith("?")) {
      parsed = new URL(`${NEON_CALLBACK_REDIRECT_URI}${trimmed}`);
    } else {
      throw new Error("Expected a full callback URL such as http://127.0.0.1:44555/callback?code=...");
    }
  }
  const returnedState = parsed.searchParams.get("state");
  if (!returnedState) {
    throw new Error("The pasted callback URL did not include a state parameter.");
  }
  if (returnedState !== expectedState) {
    throw new Error("The pasted callback URL did not match this Neon login request.");
  }
  const errorValue = parsed.searchParams.get("error");
  if (errorValue) {
    const description = parsed.searchParams.get("error_description");
    throw new Error(description || errorValue);
  }
  const code = parsed.searchParams.get("code");
  if (!code) {
    throw new Error("The pasted callback URL did not include an authorization code.");
  }
  return parsed;
}
function formatLoginSuccessMessage(credentials) {
  const identity = getNeonIdentityLabel(credentials);
  return identity ? `Authentication complete.
Logged in to Neon as ${identity}
Run \`neon auth token\` for an OAuth bearer token or \`neon auth api-key create --name <name>\` for a long-lived personal API key.
` : "Authentication complete.\nLogged in to Neon.\nRun `neon auth token` for an OAuth bearer token or `neon auth api-key create --name <name>` for a long-lived personal API key.\n";
}
async function completePendingNeonLogin(vfs, options, callbackUrlInput, keychain) {
  const pending = readPendingNeonAuthState(vfs, options.pendingAuthPath);
  if (!pending) {
    throw new Error(
      "No pending Neon browser login was found. Run `neon auth login` to start a new login flow."
    );
  }
  const callbackUrl = parseCallbackUrl(callbackUrlInput, pending.state);
  const credentials = await exchangeNeonAuthorizationCode({
    oauthHost: pending.oauth_host || options.oauthHost,
    clientId: pending.client_id || options.clientId,
    code: callbackUrl.searchParams.get("code") || "",
    codeVerifier: pending.code_verifier,
    redirectUri: pending.redirect_uri || NEON_CALLBACK_REDIRECT_URI
  });
  const withApiKey = await mintPersonalApiKey(credentials, options);
  writeNeonCredentials(vfs, withApiKey, options.credentialsPath);
  deletePendingNeonAuthState(vfs, options.pendingAuthPath);
  await persistKeychainState(keychain);
  return withApiKey;
}
async function mintPersonalApiKey(credentials, options) {
  if (credentials.personal_api_key || !credentials.access_token) {
    return credentials;
  }
  const keyName = buildDefaultNeonApiKeyName();
  try {
    const created = await createNeonApiKey(credentials.access_token, {
      apiHost: options.apiHost,
      keyName
    });
    return {
      ...credentials,
      personal_api_key: created.key,
      personal_api_key_id: created.id != null ? String(created.id) : void 0,
      personal_api_key_name: created.name || keyName
    };
  } catch {
    return credentials;
  }
}
function parseApiKeyCreateArgs(args) {
  let keyName = null;
  let callbackUrl = null;
  let index = 0;
  while (index < args.length) {
    const arg = args[index];
    const next = args[index + 1];
    if (arg === "--name") {
      if (!next) return { keyName, callbackUrl, rest: [], error: "missing value for --name" };
      keyName = next.trim();
      index += 2;
      continue;
    }
    if (arg.startsWith("--name=")) {
      keyName = arg.slice("--name=".length).trim();
      index += 1;
      continue;
    }
    if (arg === "--callback-url") {
      if (!next) return { keyName, callbackUrl, rest: [], error: "missing value for --callback-url" };
      callbackUrl = next.trim();
      index += 2;
      continue;
    }
    if (arg.startsWith("--callback-url=")) {
      callbackUrl = arg.slice("--callback-url=".length).trim();
      index += 1;
      continue;
    }
    break;
  }
  return {
    keyName,
    callbackUrl,
    rest: args.slice(index)
  };
}
function buildDefaultApiKeyName() {
  const iso = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
  return `almostnode-${iso}`;
}
async function resolveStoredNeonCredentials(vfs, options, keychain) {
  if (options.apiKey) {
    return {
      access_token: options.apiKey,
      token_type: "Bearer"
    };
  }
  const stored = readNeonCredentials(vfs, options.credentialsPath);
  if (!stored) {
    return null;
  }
  if (stored.access_token && typeof stored.expires_at === "number" && stored.expires_at > Date.now()) {
    return stored;
  }
  if (!stored.refresh_token) {
    return stored.access_token ? stored : null;
  }
  const refreshed = await refreshNeonCredentials(stored, {
    oauthHost: options.oauthHost,
    clientId: options.clientId
  });
  writeNeonCredentials(vfs, refreshed, options.credentialsPath);
  await persistKeychainState(keychain);
  return refreshed;
}
function buildHelpText() {
  return 'neon - Neon auth integration for almostnode\n\nCommands:\n  auth                         Start the browser login flow\n  auth login                   Start the browser login flow\n  auth complete <callback-url> Finish a pending browser login using the pasted callback URL\n  auth logout                  Remove the saved Neon credentials\n  auth token                   Print the current Neon bearer token\n  auth whoami                  Show the current Neon identity\n  auth status                  Show current Neon authentication status\n  auth api-key create          Create and print a long-lived personal Neon API key\n  login                        Alias for `auth login`\n  logout                       Alias for `auth logout`\n  me                           Alias for `auth whoami`\n\nNotes:\n  In the desktop runtime, almostnode can capture the localhost callback automatically.\n  In the browser runtime, the flow mirrors neonctl OAuth, but almostnode cannot host the localhost callback.\n  After signing in, copy the final http://127.0.0.1:44555/callback?... URL from the browser\n  address bar and paste it back into the prompt, or finish it later with:\n    neon auth complete "<callback-url>"\n';
}
async function runLoginCommand(args, ctx, vfs, keychain) {
  if (signalAborted(ctx.signal)) {
    return abortResult();
  }
  const resolved = resolveCommonOptions(args, ctx);
  if (resolved.error) {
    return err(`neon auth login: ${resolved.error}
`);
  }
  if (resolved.apiKey) {
    return ok("Using NEON_API_KEY from the environment or --api-key.\n");
  }
  const existing = readNeonCredentials(vfs, resolved.credentialsPath);
  if ((existing == null ? void 0 : existing.refresh_token) || (existing == null ? void 0 : existing.access_token)) {
    const identity = getNeonIdentityLabel(existing);
    return ok(
      identity ? `Already logged in to Neon as ${identity}
  To re-authenticate, run: neon auth logout && neon auth login
` : "Already logged in to Neon.\n  To re-authenticate, run: neon auth logout && neon auth login\n"
    );
  }
  if (typeof window === "undefined") {
    return err("Neon login requires a browser environment.\n");
  }
  const { codeVerifier, codeChallenge, state } = await createNeonPkcePair();
  const desktopLoopbackBridge = getDesktopOAuthLoopbackBridge();
  let redirectUri = NEON_CALLBACK_REDIRECT_URI;
  let desktopSessionId = null;
  if (desktopLoopbackBridge) {
    try {
      const session = await desktopLoopbackBridge.createSession({
        callbackPath: "/callback"
      });
      desktopSessionId = session.sessionId;
      redirectUri = session.redirectUri;
    } catch (error) {
      return err(`Neon login failed: ${formatErrorMessage(error)}
`);
    }
  }
  const authUrl = buildNeonAuthorizationUrl({
    oauthHost: resolved.oauthHost,
    clientId: resolved.clientId,
    redirectUri,
    state,
    codeChallenge
  });
  writePendingNeonAuthState(vfs, {
    state,
    code_verifier: codeVerifier,
    oauth_host: resolved.oauthHost,
    client_id: resolved.clientId,
    redirect_uri: redirectUri,
    created_at: Date.now()
  }, resolved.pendingAuthPath);
  await persistKeychainState(keychain);
  if (desktopLoopbackBridge && desktopSessionId) {
    try {
      await desktopLoopbackBridge.openExternal({
        sessionId: desktopSessionId,
        url: authUrl
      });
    } catch {
      try {
        window.open(authUrl, "_blank");
      } catch {
      }
    }
    try {
      const { callbackUrl } = await desktopLoopbackBridge.waitForCallback({
        sessionId: desktopSessionId,
        timeoutMs: NEON_DESKTOP_AUTH_TIMEOUT_MS,
        successHtml: DESKTOP_NEON_SUCCESS_HTML
      });
      const credentials = await completePendingNeonLogin(
        vfs,
        resolved,
        callbackUrl,
        keychain
      );
      return ok(formatLoginSuccessMessage(credentials));
    } catch (error) {
      return err(
        `Neon login failed: ${formatErrorMessage(error)}
If the browser already redirected, you can still finish manually with:
  neon auth complete "<callback-url>"
`
      );
    }
  }
  try {
    window.open(authUrl, "_blank");
  } catch {
  }
  try {
    if (typeof window.alert === "function") {
      window.alert(
        `Finish the Neon login in the browser tab that just opened.

When Neon redirects to http://127.0.0.1:44555/callback and the page fails to load, copy the full URL from the address bar and paste it into the next prompt.

If the browser tab did not open, open this URL manually:
${authUrl}`
      );
    }
  } catch {
  }
  if (typeof window.prompt !== "function") {
    return err("Neon login requires a browser prompt when desktop loopback is unavailable.\n");
  }
  const pastedCallback = window.prompt(
    "Paste the full Neon callback URL from the browser address bar after login completes:",
    ""
  );
  if (!(pastedCallback == null ? void 0 : pastedCallback.trim())) {
    return err(
      'Neon login is waiting for the browser callback.\nAfter Neon redirects to http://127.0.0.1:44555/callback, run:\n  neon auth complete "<callback-url>"\n'
    );
  }
  try {
    const credentials = await completePendingNeonLogin(
      vfs,
      resolved,
      pastedCallback,
      keychain
    );
    return ok(formatLoginSuccessMessage(credentials));
  } catch (error) {
    return err(`Neon login failed: ${formatErrorMessage(error)}
`);
  }
}
async function runCompleteCommand(args, ctx, vfs, keychain) {
  var _a, _b;
  const resolved = resolveCommonOptions(args, ctx);
  if (resolved.error) {
    return err(`neon auth complete: ${resolved.error}
`);
  }
  const callbackUrl = ((_a = resolved.rest[0]) == null ? void 0 : _a.trim()) || (typeof window !== "undefined" && typeof window.prompt === "function" ? (_b = window.prompt(
    "Paste the full Neon callback URL from the browser address bar after login completes:",
    ""
  )) == null ? void 0 : _b.trim() : "");
  if (!callbackUrl) {
    return err("neon auth complete: missing callback URL\n");
  }
  try {
    const credentials = await completePendingNeonLogin(vfs, resolved, callbackUrl, keychain);
    return ok(formatLoginSuccessMessage(credentials));
  } catch (error) {
    return err(`neon auth complete: ${formatErrorMessage(error)}
`);
  }
}
async function runLogoutCommand(args, ctx, vfs, keychain) {
  const resolved = resolveCommonOptions(args, ctx);
  if (resolved.error) {
    return err(`neon auth logout: ${resolved.error}
`);
  }
  const existing = readNeonCredentials(vfs, resolved.credentialsPath);
  if ((existing == null ? void 0 : existing.access_token) && existing.personal_api_key_id) {
    try {
      await deleteNeonApiKey(existing.access_token, existing.personal_api_key_id, {
        apiHost: resolved.apiHost
      });
    } catch {
    }
  }
  const removed = deleteNeonCredentials(vfs, resolved.credentialsPath);
  const removedPending = deletePendingNeonAuthState(vfs, resolved.pendingAuthPath);
  if (removed || removedPending) {
    await persistKeychainState(keychain);
    return ok("Removed Neon login state.\n");
  }
  return ok("Neon is already logged out.\n");
}
async function runTokenCommand(args, ctx, vfs, keychain) {
  var _a;
  const resolved = resolveCommonOptions(args, ctx);
  if (resolved.error) {
    return err(`neon auth token: ${resolved.error}
`);
  }
  try {
    const credentials = await resolveStoredNeonCredentials(vfs, resolved, keychain);
    const token = (_a = credentials == null ? void 0 : credentials.access_token) == null ? void 0 : _a.trim();
    if (!token) {
      return err("Not authenticated. Run `neon auth login` first.\n");
    }
    return ok(`${token}
`);
  } catch (error) {
    return err(`neon auth token: ${formatErrorMessage(error)}
`);
  }
}
async function runWhoamiCommand(args, ctx, vfs, keychain) {
  const resolved = resolveCommonOptions(args, ctx);
  if (resolved.error) {
    return err(`neon auth whoami: ${resolved.error}
`);
  }
  if (resolved.apiKey) {
    return ok("Authenticated via NEON_API_KEY\n");
  }
  try {
    const credentials = await resolveStoredNeonCredentials(vfs, resolved, keychain);
    const identity = getNeonIdentityLabel(credentials);
    if (!(credentials == null ? void 0 : credentials.access_token)) {
      return err("Not authenticated. Run `neon auth login` first.\n");
    }
    return ok(`${identity || "authenticated"}
`);
  } catch (error) {
    return err(`neon auth whoami: ${formatErrorMessage(error)}
`);
  }
}
async function runStatusCommand(args, ctx, vfs, keychain) {
  const resolved = resolveCommonOptions(args, ctx);
  if (resolved.error) {
    return err(`neon auth status: ${resolved.error}
`);
  }
  if (resolved.apiKey) {
    return ok("Using NEON_API_KEY from the environment or --api-key.\n");
  }
  try {
    const credentials = await resolveStoredNeonCredentials(vfs, resolved, keychain);
    if (!(credentials == null ? void 0 : credentials.access_token)) {
      return ok("Not logged in to Neon. Run `neon auth login` to authenticate.\n");
    }
    const identity = getNeonIdentityLabel(credentials);
    const expiresAt = typeof credentials.expires_at === "number" ? new Date(credentials.expires_at) : null;
    const expiresLabel = expiresAt && !Number.isNaN(expiresAt.getTime()) ? expiresAt.toLocaleString() : null;
    if (identity && expiresLabel) {
      return ok(`Logged in to Neon as ${identity} (token expires ${expiresLabel})
`);
    }
    if (identity) {
      return ok(`Logged in to Neon as ${identity}
`);
    }
    if (expiresLabel) {
      return ok(`Logged in to Neon (token expires ${expiresLabel})
`);
    }
    return ok("Logged in to Neon\n");
  } catch (error) {
    return err(`neon auth status: ${formatErrorMessage(error)}
`);
  }
}
async function runApiKeyCreateCommand(args, ctx, vfs, keychain) {
  var _a;
  const resolved = resolveCommonOptions(args, ctx);
  if (resolved.error) {
    return err(`neon auth api-key create: ${resolved.error}
`);
  }
  const parsed = parseApiKeyCreateArgs(resolved.rest);
  if (parsed.error) {
    return err(`neon auth api-key create: ${parsed.error}
`);
  }
  if (parsed.rest.length > 0) {
    return err(`neon auth api-key create: unknown argument '${parsed.rest[0]}'
`, 2);
  }
  try {
    if (parsed.callbackUrl) {
      await completePendingNeonLogin(vfs, resolved, parsed.callbackUrl, keychain);
    }
    const credentials = await resolveStoredNeonCredentials(vfs, resolved, keychain);
    const accessToken = (_a = credentials == null ? void 0 : credentials.access_token) == null ? void 0 : _a.trim();
    if (!accessToken) {
      return err(
        'Not authenticated. Run `neon auth login` first, or pass `--callback-url "<callback-url>"` if a login is already pending.\n'
      );
    }
    const keyName = parsed.keyName || buildDefaultApiKeyName();
    const created = await createNeonApiKey(accessToken, {
      apiHost: resolved.apiHost,
      keyName
    });
    writeNeonCredentials(vfs, {
      ...credentials,
      personal_api_key: created.key,
      personal_api_key_id: created.id != null ? String(created.id) : void 0,
      personal_api_key_name: created.name || keyName
    }, resolved.credentialsPath);
    await persistKeychainState(keychain);
    return ok(
      `Created Neon personal API key${created.name ? ` "${created.name}"` : ""}${created.id != null ? ` (${created.id})` : ""}.
Copy it now. Neon only returns the raw key once.
${created.key}
`
    );
  } catch (error) {
    return err(`neon auth api-key create: ${formatErrorMessage(error)}
`);
  }
}
async function runApiKeyCommand(args, ctx, vfs, keychain) {
  const [subcommand = "create", ...rest] = args;
  switch (subcommand) {
    case "create":
      return runApiKeyCreateCommand(rest, ctx, vfs, keychain);
    default:
      return err(`neon auth api-key: unknown command '${subcommand}'
`, 2);
  }
}
async function runAuthCommand(args, ctx, vfs, keychain) {
  const [subcommand = "login", ...rest] = args;
  switch (subcommand) {
    case "login":
      return runLoginCommand(rest, ctx, vfs, keychain);
    case "complete":
      return runCompleteCommand(rest, ctx, vfs, keychain);
    case "logout":
      return runLogoutCommand(rest, ctx, vfs, keychain);
    case "token":
      return runTokenCommand(rest, ctx, vfs, keychain);
    case "whoami":
      return runWhoamiCommand(rest, ctx, vfs, keychain);
    case "status":
      return runStatusCommand(rest, ctx, vfs, keychain);
    case "api-key":
      return runApiKeyCommand(rest, ctx, vfs, keychain);
    default:
      return err(`neon auth: unknown command '${subcommand}'
`, 2);
  }
}
async function runNeonCommand(args, ctx, vfs, keychain) {
  if (signalAborted(ctx.signal)) {
    return abortResult();
  }
  try {
    const [subcommand, ...rest] = args;
    switch (subcommand) {
      case void 0:
      case "help":
      case "--help":
        return ok(buildHelpText());
      case "auth":
        return runAuthCommand(rest, ctx, vfs, keychain);
      case "login":
        return runLoginCommand(rest, ctx, vfs, keychain);
      case "logout":
        return runLogoutCommand(rest, ctx, vfs, keychain);
      case "me":
        return runWhoamiCommand(rest, ctx, vfs, keychain);
      case "version":
      case "--version":
        return ok("neon v0.0.0-almostnode\n");
      default:
        return err(`neon: unknown command '${subcommand}'
`, 2);
    }
  } catch (error) {
    if (signalAborted(ctx.signal)) {
      return abortResult();
    }
    return err(`neon: ${formatErrorMessage(error)}
`);
  }
}
export {
  runNeonCommand
};
//# sourceMappingURL=neon-command-BO4WAnH7.js.map
