{"version":3,"sources":["../../src/lib/authClient.ts"],"names":[],"mappings":"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","file":"authClient.mjs","sourcesContent":["import type {\n  AuthError,\n  AuthErrorCode,\n  AuthUser,\n  LoginMethods,\n  ResetPasswordResult,\n  SessionResult,\n  SignInResult,\n  SignUpResult,\n  VerifyEmailResult,\n} from '../types/auth';\n\n/**\n * Resolve the auth API base path from the current hostname.\n *\n * - `*.bffless.app` (or `bffless.app`) → `/api/auth` (SuperTokens flow,\n *   parent-domain cookies, SSO with admin).\n * - Anything else (custom domains) → `/_bffless/auth` (domain-scoped JWT\n *   flow that wraps SuperTokens recipes server-side).\n */\nexport function resolveAuthBasePath(hostnameOverride?: string): string {\n  let hostname = hostnameOverride;\n  if (hostname == null) {\n    if (typeof window === 'undefined' || !window.location) {\n      return '/api/auth';\n    }\n    hostname = window.location.hostname;\n  }\n  const lower = hostname.toLowerCase();\n  if (lower === 'bffless.app' || lower.endsWith('.bffless.app')) {\n    return '/api/auth';\n  }\n  return '/_bffless/auth';\n}\n\nconst HEADERS_JSON = { 'Content-Type': 'application/json' } as const;\n\nexport class AuthClientError extends Error {\n  readonly code: AuthErrorCode;\n  constructor(code: AuthErrorCode, message: string) {\n    super(message);\n    this.code = code;\n    this.name = 'AuthClientError';\n  }\n}\n\nfunction makeError(code: AuthErrorCode, message: string): AuthError {\n  return { code, message };\n}\n\nasync function readJson(res: Response): Promise<any> {\n  try {\n    return await res.json();\n  } catch {\n    return null;\n  }\n}\n\nfunction normalizeUser(raw: any): AuthUser | null {\n  if (!raw || typeof raw !== 'object') return null;\n  if (typeof raw.id !== 'string' || typeof raw.email !== 'string') return null;\n  return {\n    id: raw.id,\n    email: raw.email,\n    role: raw.role ?? null,\n  };\n}\n\nexport interface AuthFetchOptions {\n  basePath: string;\n  signal?: AbortSignal;\n}\n\n/**\n * Surface-specific refresh endpoint. Both backends mint short-lived access\n * tokens that need to be exchanged for a new one when expired.\n *\n * - `/api/auth` (SuperTokens): `POST /api/auth/session/refresh` — handled\n *   directly by the SuperTokens middleware, which validates the\n *   `sRefreshToken` cookie and rotates `sAccessToken`.\n * - `/_bffless/auth` (custom-domain JWT): `POST /_bffless/auth/refresh` —\n *   `CustomDomainAuthController.refresh` validates the `bffless_refresh`\n *   cookie and re-issues `bffless_access`.\n */\nfunction refreshUrlFor(basePath: string): string {\n  return basePath === '/api/auth' ? `${basePath}/session/refresh` : `${basePath}/refresh`;\n}\n\nasync function attemptSessionRefresh(opts: AuthFetchOptions): Promise<boolean> {\n  try {\n    const res = await fetch(refreshUrlFor(opts.basePath), {\n      method: 'POST',\n      credentials: 'include',\n      signal: opts.signal,\n    });\n    return res.ok;\n  } catch {\n    return false;\n  }\n}\n\nasync function fetchSessionOnce(opts: AuthFetchOptions): Promise<Response | null> {\n  try {\n    return await fetch(`${opts.basePath}/session`, {\n      method: 'GET',\n      credentials: 'include',\n      signal: opts.signal,\n    });\n  } catch {\n    return null;\n  }\n}\n\n/**\n * GET ${basePath}/session — returns the current user (or null if not signed in).\n *\n * Both base paths return shapes the client can normalize:\n * - `/api/auth/session` (SessionAuthGuard): returns `{ user: {...} }` or 401\n * - `/_bffless/auth/session`: returns `{ authenticated, user }`\n *\n * On a 401 we attempt one silent refresh (cookie rotation, no body) and retry.\n * The custom-domain backend specifically signals this case with\n * `{ message: 'try refresh token' }`; the SuperTokens path returns plain 401s\n * but its refresh endpoint is idempotent enough that we can always try.\n * If the refresh itself returns non-OK we treat the user as signed-out\n * without bubbling an error — same as the no-cookie case.\n */\nasync function fetchSessionImpl(opts: AuthFetchOptions): Promise<SessionResult> {\n  let res = await fetchSessionOnce(opts);\n  if (!res) return { user: null };\n\n  if (res.status === 401) {\n    const refreshed = await attemptSessionRefresh(opts);\n    if (!refreshed) return { user: null };\n    res = await fetchSessionOnce(opts);\n    if (!res) return { user: null };\n  }\n\n  if (!res.ok) return { user: null };\n  const data = await readJson(res);\n  if (!data) return { user: null };\n  return { user: normalizeUser(data.user) };\n}\n\n// Per-basePath in-flight dedup so multiple useAuth instances mounting on the\n// same render tick (e.g. an AuthDialog island in the header + a gated content\n// island on the page) share a single network request. The cache entry is\n// cleared as soon as the request settles, so subsequent mounts after that\n// trigger a fresh fetch — this is just to collapse simultaneous parallel\n// fetches, not to cache results across time.\n//\n// Signal is intentionally NOT forwarded when deduping — aborting one caller\n// would also reject every other caller awaiting the shared promise. useAuth's\n// own `cancelled` closure flag handles unmount-during-fetch correctness.\nconst sessionInFlight = new Map<string, Promise<SessionResult>>();\n\nexport function fetchSession(opts: AuthFetchOptions): Promise<SessionResult> {\n  const key = opts.basePath;\n  const existing = sessionInFlight.get(key);\n  if (existing) return existing;\n  const p = fetchSessionImpl({ basePath: opts.basePath }).finally(() => {\n    sessionInFlight.delete(key);\n  });\n  sessionInFlight.set(key, p);\n  return p;\n}\n\nexport async function signIn(\n  opts: AuthFetchOptions,\n  body: { email: string; password: string },\n): Promise<SignInResult> {\n  let res: Response;\n  try {\n    res = await fetch(`${opts.basePath}/signin`, {\n      method: 'POST',\n      credentials: 'include',\n      headers: HEADERS_JSON,\n      body: JSON.stringify(body),\n      signal: opts.signal,\n    });\n  } catch (err) {\n    throw new AuthClientError('network', 'Network error. Please try again.');\n  }\n\n  const data = await readJson(res);\n\n  if (res.ok) {\n    if (data?.status === 'WRONG_CREDENTIALS_ERROR') {\n      throw new AuthClientError('wrong_credentials', 'Incorrect email or password.');\n    }\n    const user = normalizeUser(data?.user);\n    if (!user) throw new AuthClientError('unknown', 'Unexpected sign-in response.');\n    return { user };\n  }\n\n  if (res.status === 401) {\n    throw new AuthClientError('wrong_credentials', 'Incorrect email or password.');\n  }\n  throw new AuthClientError('unknown', data?.message || 'Sign-in failed.');\n}\n\nexport async function signUp(\n  opts: AuthFetchOptions,\n  body: { email: string; password: string; redirect?: string },\n): Promise<SignUpResult> {\n  let res: Response;\n  try {\n    res = await fetch(`${opts.basePath}/signup`, {\n      method: 'POST',\n      credentials: 'include',\n      headers: HEADERS_JSON,\n      body: JSON.stringify(body),\n      signal: opts.signal,\n    });\n  } catch {\n    throw new AuthClientError('network', 'Network error. Please try again.');\n  }\n\n  const data = await readJson(res);\n\n  if (res.ok) {\n    if (data?.status === 'EMAIL_ALREADY_EXISTS_ERROR') {\n      throw new AuthClientError('email_exists', 'An account with that email already exists.');\n    }\n    if (data?.status === 'PUBLIC_SIGNUP_DISABLED') {\n      throw new AuthClientError(\n        'signup_disabled',\n        \"This site doesn't accept new signups. If you already have an account, sign in.\",\n      );\n    }\n    const user = normalizeUser(data?.user);\n    if (!user) throw new AuthClientError('unknown', 'Unexpected sign-up response.');\n    return {\n      user,\n      emailVerificationRequired: !!data?.emailVerificationRequired,\n    };\n  }\n\n  // /api/auth/signup throws BadRequest with message strings\n  const msg = data?.message || '';\n  if (/already exists/i.test(msg)) {\n    throw new AuthClientError('email_exists', 'An account with that email already exists.');\n  }\n  // Project-level gate (\"Public signups are not enabled for this site...\") —\n  // check before the workspace-level `registration_disabled` heuristic.\n  if (/public signups (are not|aren'?t) enabled/i.test(msg)) {\n    throw new AuthClientError(\n      'signup_disabled',\n      \"This site doesn't accept new signups. If you already have an account, sign in.\",\n    );\n  }\n  if (/registration/i.test(msg) && /(disabled|not available)/i.test(msg)) {\n    throw new AuthClientError('registration_disabled', msg);\n  }\n  if (/8 characters/i.test(msg)) {\n    throw new AuthClientError('weak_password', msg);\n  }\n  if (/email/i.test(msg) && /required/i.test(msg)) {\n    throw new AuthClientError('invalid_email', msg);\n  }\n  throw new AuthClientError('unknown', msg || 'Sign-up failed.');\n}\n\nexport async function forgotPassword(\n  opts: AuthFetchOptions,\n  body: { email: string },\n): Promise<void> {\n  try {\n    await fetch(`${opts.basePath}/forgot-password`, {\n      method: 'POST',\n      credentials: 'include',\n      headers: HEADERS_JSON,\n      body: JSON.stringify(body),\n      signal: opts.signal,\n    });\n  } catch {\n    throw new AuthClientError('network', 'Network error. Please try again.');\n  }\n  // Always success — endpoint deliberately doesn't reveal email existence.\n}\n\nexport async function resetPassword(\n  opts: AuthFetchOptions,\n  body: { token: string; password: string },\n): Promise<ResetPasswordResult> {\n  let res: Response;\n  try {\n    res = await fetch(`${opts.basePath}/reset-password`, {\n      method: 'POST',\n      credentials: 'include',\n      headers: HEADERS_JSON,\n      body: JSON.stringify(body),\n      signal: opts.signal,\n    });\n  } catch {\n    throw new AuthClientError('network', 'Network error. Please try again.');\n  }\n\n  const data = await readJson(res);\n\n  if (res.ok) {\n    if (data?.status === 'RESET_PASSWORD_INVALID_TOKEN_ERROR') {\n      throw new AuthClientError(\n        'invalid_token',\n        'This reset link is invalid or has expired. Please request a new one.',\n      );\n    }\n    return { user: normalizeUser(data?.user) };\n  }\n\n  const msg = data?.message || 'Failed to reset password.';\n  if (/invalid|expired/i.test(msg)) {\n    throw new AuthClientError('invalid_token', msg);\n  }\n  throw new AuthClientError('unknown', msg);\n}\n\nexport async function verifyEmail(\n  opts: AuthFetchOptions,\n  body: { token: string },\n): Promise<VerifyEmailResult> {\n  let res: Response;\n  try {\n    res = await fetch(`${opts.basePath}/verify-email`, {\n      method: 'POST',\n      credentials: 'include',\n      headers: HEADERS_JSON,\n      body: JSON.stringify(body),\n      signal: opts.signal,\n    });\n  } catch {\n    throw new AuthClientError('network', 'Network error. Please try again.');\n  }\n\n  const data = await readJson(res);\n\n  if (res.ok) {\n    if (data?.status === 'EMAIL_VERIFICATION_INVALID_TOKEN_ERROR') {\n      throw new AuthClientError(\n        'invalid_token',\n        'This verification link is invalid or has expired.',\n      );\n    }\n    return { user: normalizeUser(data?.user) };\n  }\n\n  const msg = data?.message || 'Failed to verify email.';\n  if (/invalid|expired/i.test(msg)) {\n    throw new AuthClientError('invalid_token', msg);\n  }\n  throw new AuthClientError('unknown', msg);\n}\n\nexport async function resendVerification(opts: AuthFetchOptions): Promise<void> {\n  try {\n    await fetch(`${opts.basePath}/send-verification-email`, {\n      method: 'POST',\n      credentials: 'include',\n      headers: HEADERS_JSON,\n      body: '{}',\n      signal: opts.signal,\n    });\n  } catch {\n    throw new AuthClientError('network', 'Network error. Please try again.');\n  }\n}\n\nexport async function signOut(opts: AuthFetchOptions): Promise<void> {\n  // /api/auth uses 'signout', /_bffless/auth uses 'logout'\n  const path = opts.basePath.endsWith('/api/auth') ? 'signout' : 'logout';\n  try {\n    await fetch(`${opts.basePath}/${path}`, {\n      method: 'POST',\n      credentials: 'include',\n      headers: HEADERS_JSON,\n      body: '{}',\n      signal: opts.signal,\n    });\n  } catch {\n    // best-effort; consumer should still reflect signed-out state\n  }\n}\n\n/**\n * Conservative LoginMethods value used when the network call fails or the\n * endpoint isn't available. Defaults are: password on, no google, signup\n * allowed at the workspace level (so older backends without the namespaced\n * shape don't accidentally hide the Sign up tab).\n */\nfunction defaultLoginMethods(): LoginMethods {\n  return {\n    hasPassword: true,\n    hasGoogle: false,\n    workspace: { hasPassword: true, hasGoogle: false, allowSignup: true },\n  };\n}\n\nasync function fetchLoginMethodsImpl(opts: AuthFetchOptions): Promise<LoginMethods> {\n  let res: Response;\n  try {\n    res = await fetch(`${opts.basePath}/login-methods`, {\n      method: 'GET',\n      credentials: 'include',\n    });\n  } catch {\n    return defaultLoginMethods();\n  }\n  if (!res.ok) return defaultLoginMethods();\n  const data = await readJson(res);\n\n  // New backends return a `workspace` (and optional `project`) namespace.\n  // Older backends return only the flat `{ hasPassword, hasGoogle }` shape;\n  // synthesize the namespace from those values so downstream code can read\n  // from `workspace.*` unconditionally.\n  const hasPassword = data?.hasPassword ?? data?.workspace?.hasPassword ?? true;\n  const hasGoogle = !!(data?.hasGoogle ?? data?.workspace?.hasGoogle);\n  const workspace = data?.workspace ?? {\n    hasPassword,\n    hasGoogle,\n    allowSignup: true, // Older backends don't surface the gate; assume allowed.\n  };\n\n  return {\n    hasPassword,\n    hasGoogle,\n    workspace,\n    ...(data?.project ? { project: data.project } : {}),\n  };\n}\n\n// Per-basePath in-flight dedup; see fetchSession above for the rationale.\nconst loginMethodsInFlight = new Map<string, Promise<LoginMethods>>();\n\nexport function fetchLoginMethods(opts: AuthFetchOptions): Promise<LoginMethods> {\n  const key = opts.basePath;\n  const existing = loginMethodsInFlight.get(key);\n  if (existing) return existing;\n  const p = fetchLoginMethodsImpl({ basePath: opts.basePath }).finally(() => {\n    loginMethodsInFlight.delete(key);\n  });\n  loginMethodsInFlight.set(key, p);\n  return p;\n}\n\n"]}