@xylex-group/athena 2.12.0 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +1190 -1184
  3. package/bin/athena-js.js +104 -76
  4. package/dist/admin.cjs +45 -0
  5. package/dist/admin.cjs.map +1 -0
  6. package/dist/admin.d.cts +64 -0
  7. package/dist/admin.d.ts +64 -0
  8. package/dist/admin.js +41 -0
  9. package/dist/admin.js.map +1 -0
  10. package/dist/athena-auth-url-oLux_57a.d.cts +377 -0
  11. package/dist/athena-auth-url-oLux_57a.d.ts +377 -0
  12. package/dist/browser.cjs +33 -46
  13. package/dist/browser.cjs.map +1 -1
  14. package/dist/browser.d.cts +12 -10
  15. package/dist/browser.d.ts +12 -10
  16. package/dist/browser.js +33 -46
  17. package/dist/browser.js.map +1 -1
  18. package/dist/cli/index.cjs +150 -48
  19. package/dist/cli/index.cjs.map +1 -1
  20. package/dist/cli/index.d.cts +14 -5
  21. package/dist/cli/index.d.ts +14 -5
  22. package/dist/cli/index.js +150 -49
  23. package/dist/cli/index.js.map +1 -1
  24. package/dist/{client-QUbAs7E8.d.ts → client-BJjUwDSg.d.cts} +109 -1448
  25. package/dist/{client-C3x75Zgn.d.cts → client-DVOKSYDI.d.ts} +109 -1448
  26. package/dist/cookies.cjs +18 -0
  27. package/dist/cookies.cjs.map +1 -1
  28. package/dist/cookies.d.cts +2 -1
  29. package/dist/cookies.d.ts +2 -1
  30. package/dist/cookies.js +17 -1
  31. package/dist/cookies.js.map +1 -1
  32. package/dist/{index-CVcQCGyG.d.ts → index-CFL9xbFR.d.cts} +2 -0
  33. package/dist/{index-CVcQCGyG.d.cts → index-UKJpunc6.d.ts} +2 -0
  34. package/dist/index.cjs +101 -46
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.cts +13 -10
  37. package/dist/index.d.ts +13 -10
  38. package/dist/index.js +101 -47
  39. package/dist/index.js.map +1 -1
  40. package/dist/{model-form-CD1uhWSh.d.cts → model-form-Dw4zEL5a.d.cts} +2 -2
  41. package/dist/{model-form-Dm69I-oO.d.ts → model-form-yRg71q3H.d.ts} +2 -2
  42. package/dist/{module-CW3tWJ10.d.ts → module-DBteUIob.d.ts} +12 -9
  43. package/dist/{module-Cxcurfes.d.cts → module-yoX49uQC.d.cts} +12 -9
  44. package/dist/next/client.cjs +452 -46
  45. package/dist/next/client.cjs.map +1 -1
  46. package/dist/next/client.d.cts +7 -4
  47. package/dist/next/client.d.ts +7 -4
  48. package/dist/next/client.js +430 -47
  49. package/dist/next/client.js.map +1 -1
  50. package/dist/next/server.cjs +292 -46
  51. package/dist/next/server.cjs.map +1 -1
  52. package/dist/next/server.d.cts +81 -5
  53. package/dist/next/server.d.ts +81 -5
  54. package/dist/next/server.js +280 -47
  55. package/dist/next/server.js.map +1 -1
  56. package/dist/organization.cjs +72 -0
  57. package/dist/organization.cjs.map +1 -0
  58. package/dist/organization.d.cts +43 -0
  59. package/dist/organization.d.ts +43 -0
  60. package/dist/organization.js +70 -0
  61. package/dist/organization.js.map +1 -0
  62. package/dist/payload-BzVbUgY_.d.cts +219 -0
  63. package/dist/payload-DEOWN_oo.d.ts +219 -0
  64. package/dist/{pipeline-BAwb6Vzm.d.ts → pipeline-Bj6RWt1A.d.ts} +1 -1
  65. package/dist/{pipeline-B14jVK7J.d.cts → pipeline-Dwck-wZO.d.cts} +1 -1
  66. package/dist/react.cjs +2 -10
  67. package/dist/react.cjs.map +1 -1
  68. package/dist/react.d.cts +26 -7
  69. package/dist/react.d.ts +26 -7
  70. package/dist/react.js +2 -10
  71. package/dist/react.js.map +1 -1
  72. package/dist/session-cookie-detection-BqOp9mO6.d.cts +46 -0
  73. package/dist/session-cookie-detection-BqOp9mO6.d.ts +46 -0
  74. package/dist/social-providers.cjs +4189 -0
  75. package/dist/social-providers.cjs.map +1 -0
  76. package/dist/social-providers.d.cts +4948 -0
  77. package/dist/social-providers.d.ts +4948 -0
  78. package/dist/social-providers.js +4117 -0
  79. package/dist/social-providers.js.map +1 -0
  80. package/dist/{types-Cq4-NoB4.d.ts → types-BRP7sfSF.d.ts} +50 -2
  81. package/dist/{types-Dr849HD6.d.cts → types-BU8uJH_b.d.cts} +50 -2
  82. package/dist/{types-CwJCPpLD.d.ts → types-CH78O90i.d.cts} +2 -2
  83. package/dist/{types-CwJCPpLD.d.cts → types-CH78O90i.d.ts} +2 -2
  84. package/dist/{types-DMOoYnPS.d.cts → types-CjC9_5ZQ.d.cts} +3 -3
  85. package/dist/{types-BcVmPBP-.d.ts → types-DPgejxYC.d.ts} +3 -3
  86. package/dist/types-eAKAh71s.d.cts +1476 -0
  87. package/dist/types-eAKAh71s.d.ts +1476 -0
  88. package/dist/utils.cjs +438 -12
  89. package/dist/utils.cjs.map +1 -1
  90. package/dist/utils.d.cts +76 -11
  91. package/dist/utils.d.ts +76 -11
  92. package/dist/utils.js +390 -13
  93. package/dist/utils.js.map +1 -1
  94. package/package.json +49 -22
  95. package/dist/shared-0Kdc74lu.d.ts +0 -35
  96. package/dist/shared-C0wVICRv.d.cts +0 -35
package/dist/utils.d.ts CHANGED
@@ -1,4 +1,7 @@
1
- import { I as BackendOption } from './types-CwJCPpLD.js';
1
+ import { E as EnvLike } from './athena-auth-url-oLux_57a.js';
2
+ export { A as ATHENA_AUTH_COOKIE_PREFIXES, o as ATHENA_AUTH_DISABLE_COOKIE_CACHE_QUERY_PARAM, p as ATHENA_AUTH_DISABLE_COOKIE_CACHE_QUERY_VALUE, q as ATHENA_AUTH_GET_SESSION_ABSOLUTE_PATH, t as ATHENA_AUTH_GET_SESSION_PATH, a as ATHENA_AUTH_PATH, b as ATHENA_AUTH_UPSTREAM_ENV_KEYS, c as ATHENA_AUTH_UPSTREAM_URL_ENV_NAMES, u as ATHENA_AUTH_VERIFY_EMAIL_PATH, v as ATHENA_SESSION_DATA_HEADER, w as AUTHENTICATED_REDIRECT_MODE_SET, x as AUTHENTICATED_REDIRECT_VIEW_SET, d as AUTH_DEFAULT_VIEW, y as AUTH_MODE_REDIRECTS, z as AUTH_MODE_SET, e as AUTH_ROUTES, B as AUTH_SESSION_PATH, F as AUTH_TWO_FACTOR_SEGMENT, f as AUTH_VIEW_BY_SEGMENT, G as AthenaAuthClientBaseUrlOptions, H as AthenaAuthUpstreamEnv, I as AthenaAuthUpstreamEnvKey, J as AuthMode, K as AuthModeRedirects, L as AuthRoutes, g as AuthView, C as ClearAuthCookiesOptions, D as DEFAULT_ATHENA_AUTH_ORIGIN, M as DEFAULT_ATHENA_AUTH_UPSTREAM_URL, N as DEFAULT_AUTH_COOKIE_PREFIXES, O as DISABLE_COOKIE_CACHE_QUERY_PARAM, P as DISABLE_COOKIE_CACHE_QUERY_VALUE, Q as LOCAL_DEV_ORIGIN, S as SESSION_DATA_HEADER, h as clearAuthCookies, R as createAuthModeRedirects, T as createAuthRoutes, U as createFreshSessionLookupUrl, i as isAbsoluteUrl, V as isAuthMode, n as normalizeAthenaAuthBaseUrl, W as readAthenaAuthUpstreamUrlFromEnv, r as resolveAthenaAuthClientBaseUrl, j as resolveAthenaAuthRequestUrl, k as resolveAthenaAuthUpstreamUrl, X as resolveAuthModeRedirect, l as resolveAuthViewFromSegment, m as resolveEmailVerificationCallbackUrl, Y as shouldRedirectAuthenticatedAuthMode, s as shouldRedirectAuthenticatedAuthView } from './athena-auth-url-oLux_57a.js';
3
+ export { S as SESSION_COOKIE_PATTERNS, h as hasAuthSessionCookie } from './session-cookie-detection-BqOp9mO6.js';
4
+ import { z as BackendOption } from './types-CH78O90i.js';
2
5
 
3
6
  declare function slugify(input: string): string;
4
7
 
@@ -11,24 +14,74 @@ declare function asRecord(value: unknown): Record<string, unknown> | null;
11
14
  declare function asIdentifier(value: unknown): string | null;
12
15
  declare function firstString(record: Record<string, unknown> | null | undefined, keys: readonly string[]): string | null;
13
16
  declare function readTrimmedString(value: unknown): string | null;
17
+ /**
18
+ * Trim a string value; return `undefined` when not a non-empty string.
19
+ *
20
+ * Unlike {@link asString}, does not coerce numbers/bigints.
21
+ * Unlike {@link readTrimmedString}, returns `undefined` instead of `null`
22
+ * (handy for optional fields and `??` defaults).
23
+ */
24
+ declare function asNonEmptyString(value: unknown): string | undefined;
14
25
  declare function asNumber(value: unknown): number | null;
15
26
  declare function asStringArray(value: unknown): string[];
16
27
 
17
28
  declare function parseBooleanFlag(rawValue: string | undefined, fallback: boolean): boolean;
18
29
 
30
+ /**
31
+ * Read the first non-empty trimmed environment variable from a name list.
32
+ *
33
+ * @param names - Candidate env keys in priority order
34
+ * @param env - Optional env map (defaults to `process.env`)
35
+ * @returns Trimmed value of the first key that is set and non-empty
36
+ * @throws {Error} When none of the keys yield a non-empty value
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * import { requireEnv } from "@xylex-group/athena/utils"
41
+ *
42
+ * const authUrl = requireEnv([
43
+ * "ATHENA_AUTH_UPSTREAM_URL",
44
+ * "ATHENA_AUTH_URL",
45
+ * "NEXT_PUBLIC_ATHENA_AUTH_URL",
46
+ * ])
47
+ * ```
48
+ */
49
+ declare function requireEnv(names: readonly string[], env?: EnvLike): string;
50
+ /**
51
+ * Like {@link requireEnv}, but returns `undefined` instead of throwing when
52
+ * none of the keys are set.
53
+ */
54
+ declare function readEnv(names: readonly string[], env?: EnvLike): string | undefined;
55
+
19
56
  declare function isLocalHostname(hostname: string): boolean;
20
57
 
21
- interface ClearAuthCookiesOptions {
22
- prefixes?: string[];
23
- hostname?: string;
24
- path?: string;
25
- cookieHeader?: string;
58
+ /**
59
+ * Request header / Next.js helpers used by middleware and RSC session loaders.
60
+ * Framework-agnostic (no Next imports).
61
+ */
62
+ /**
63
+ * True when Next.js threw because the route used dynamic APIs during static
64
+ * generation (`DYNAMIC_SERVER_USAGE` digest or matching message).
65
+ *
66
+ * Catch and rethrow (or handle) so Next can mark the route dynamic.
67
+ */
68
+ declare function isDynamicServerUsageError(error: unknown): boolean;
69
+ interface GetOriginFromHeadersOptions {
70
+ /**
71
+ * When `x-forwarded-proto` / scheme is missing, use `http` if true else `https`.
72
+ * Typical: `process.env.NODE_ENV !== "production"`.
73
+ */
74
+ preferHttpWhenMissingProto?: boolean;
26
75
  }
27
76
  /**
28
- * Clears Athena/Better Auth browser cookies by prefix.
29
- * Returns the cookie names that matched and were targeted for deletion.
77
+ * Reconstruct public origin from request headers (Origin, or Host + proto).
78
+ *
79
+ * Prefers `Origin`, then `x-forwarded-host` / `host` with
80
+ * `x-forwarded-proto` (first value when comma-separated).
30
81
  */
31
- declare function clearAuthCookies(options?: ClearAuthCookiesOptions): string[];
82
+ declare function getOriginFromHeaders(headersList: {
83
+ get: (name: string) => string | null;
84
+ }, options?: GetOriginFromHeadersOptions): string | null;
32
85
 
33
86
  declare function proxyRequestHeaders(request: Request): Headers;
34
87
 
@@ -37,7 +90,7 @@ interface BuildAthenaRequestHeadersInput {
37
90
  profile: AthenaRequestHeaderProfile;
38
91
  sdkHeaderValue: string;
39
92
  apiKey?: string | null;
40
- /** Overrides `X-Athena-Key` while leaving `apikey` / `x-api-key` on `apiKey`. */
93
+ /** Overrides the canonical `X-Athena-Key` header value. */
41
94
  athenaKey?: string | null;
42
95
  client?: string | null;
43
96
  userId?: string | null;
@@ -85,6 +138,18 @@ declare function buildServiceRequestHeaders(profile: Exclude<AthenaRequestHeader
85
138
  declare function applyAthenaApiKeyHeaders(headers: Record<string, string>, apiKey?: string | null, athenaKey?: string | null): void;
86
139
  declare function applyAthenaAuthContextHeaders(headers: Record<string, string>, input: Pick<BuildAthenaRequestHeadersInput, 'bearerToken' | 'cookie' | 'sessionToken' | 'profile' | 'configHeaders' | 'callHeaders'>): void;
87
140
  declare function applyAthenaPgUriHeaders(headers: Record<string, string>, input: Pick<BuildAthenaRequestHeadersInput, 'pgUri' | 'jdbcUrl' | 'configHeaders' | 'callHeaders'>): void;
141
+ /**
142
+ * Minimal gateway/data request headers used by many apps before they adopt
143
+ * the full {@link buildAthenaRequestHeaders} profile model.
144
+ *
145
+ * Additive convenience — does not replace client-built headers. Prefer
146
+ * `createClient({ client, key })` so the SDK sets these on every call.
147
+ */
148
+ declare function buildAthenaGatewayHeaders(input: {
149
+ clientName?: string | null;
150
+ gatewayKey?: string | null;
151
+ headers?: Record<string, string | null | undefined>;
152
+ }): Record<string, string>;
88
153
  declare function buildAthenaRequestHeaders(input: BuildAthenaRequestHeadersInput): Record<string, string>;
89
154
 
90
155
  /**
@@ -118,4 +183,4 @@ declare function sqlJsonbLiteral(value: unknown): string;
118
183
  */
119
184
  declare function sqlBigInt(value: bigint | number): string;
120
185
 
121
- export { type AthenaRequestHeaderOverrideFields, type AthenaRequestHeaderProfile, type BuildAthenaRequestHeadersInput, type ClearAuthCookiesOptions, type ResolvedRequestHeaderOverrides, applyAthenaApiKeyHeaders, applyAthenaAuthContextHeaders, applyAthenaPgUriHeaders, asBoolean, asBooleanOrNull, asIdentifier, asNumber, asRecord, asString, asStringArray, buildAthenaRequestHeaders, buildServiceRequestHeaders, clearAuthCookies, escapeLikePatternValue, firstString, hasHeaderIgnoreCase, isLocalHostname, parseBooleanFlag, proxyRequestHeaders, quoteSqlStringLiteral, readTrimmedString, resolveHeaderValue, resolveRequestHeaderOverrides, slugify, sqlBigInt, sqlJsonbLiteral, sqlNullableText, sqlText, trimTrailingSlashes };
186
+ export { type AthenaRequestHeaderOverrideFields, type AthenaRequestHeaderProfile, type BuildAthenaRequestHeadersInput, EnvLike, type GetOriginFromHeadersOptions, type ResolvedRequestHeaderOverrides, applyAthenaApiKeyHeaders, applyAthenaAuthContextHeaders, applyAthenaPgUriHeaders, asBoolean, asBooleanOrNull, asIdentifier, asNonEmptyString, asNumber, asRecord, asString, asStringArray, buildAthenaGatewayHeaders, buildAthenaRequestHeaders, buildServiceRequestHeaders, escapeLikePatternValue, firstString, getOriginFromHeaders, hasHeaderIgnoreCase, isDynamicServerUsageError, isLocalHostname, parseBooleanFlag, proxyRequestHeaders, quoteSqlStringLiteral, readEnv, readTrimmedString, requireEnv, resolveHeaderValue, resolveRequestHeaderOverrides, slugify, sqlBigInt, sqlJsonbLiteral, sqlNullableText, sqlText, trimTrailingSlashes };
package/dist/utils.js CHANGED
@@ -68,6 +68,13 @@ function readTrimmedString(value) {
68
68
  const trimmed = value.trim();
69
69
  return trimmed.length > 0 ? trimmed : null;
70
70
  }
71
+ function asNonEmptyString(value) {
72
+ if (typeof value !== "string") {
73
+ return void 0;
74
+ }
75
+ const normalized = value.trim();
76
+ return normalized.length > 0 ? normalized : void 0;
77
+ }
71
78
  function asNumber(value) {
72
79
  if (typeof value === "number" && Number.isFinite(value)) return value;
73
80
  if (typeof value === "string" && value.trim().length > 0) {
@@ -94,6 +101,46 @@ function parseBooleanFlag(rawValue, fallback) {
94
101
  return fallback;
95
102
  }
96
103
 
104
+ // src/utils/require-env.ts
105
+ function requireEnv(names, env) {
106
+ if (!names.length) {
107
+ throw new Error(
108
+ "requireEnv() requires at least one environment variable name."
109
+ );
110
+ }
111
+ const source = env ?? readProcessEnv();
112
+ for (const name of names) {
113
+ const value = source[name]?.trim();
114
+ if (value) {
115
+ return value;
116
+ }
117
+ }
118
+ throw new Error(
119
+ `Missing required environment variable. Expected one of: ${names.join(", ")}`
120
+ );
121
+ }
122
+ function readEnv(names, env) {
123
+ if (!names.length) {
124
+ return void 0;
125
+ }
126
+ const source = env ?? readProcessEnv();
127
+ for (const name of names) {
128
+ const value = source[name]?.trim();
129
+ if (value) {
130
+ return value;
131
+ }
132
+ }
133
+ return void 0;
134
+ }
135
+ function readProcessEnv() {
136
+ try {
137
+ const processEnv = globalThis.process?.env;
138
+ return processEnv ?? {};
139
+ } catch {
140
+ return {};
141
+ }
142
+ }
143
+
97
144
  // src/utils/hostname.ts
98
145
  var LOCAL_IPV4_PATTERN = /^127(?:\.\d{1,3}){3}$/;
99
146
  function isLocalHostname(hostname) {
@@ -110,13 +157,41 @@ function isLocalHostname(hostname) {
110
157
  return false;
111
158
  }
112
159
 
160
+ // src/utils/request-origin.ts
161
+ function isDynamicServerUsageError(error) {
162
+ if (!error || typeof error !== "object") {
163
+ return false;
164
+ }
165
+ const err = error;
166
+ if (err.digest === "DYNAMIC_SERVER_USAGE") {
167
+ return true;
168
+ }
169
+ return typeof err.message === "string" && err.message.includes("Dynamic server usage:");
170
+ }
171
+ function getOriginFromHeaders(headersList, options = {}) {
172
+ const origin = headersList.get("origin")?.trim();
173
+ if (origin) {
174
+ return origin;
175
+ }
176
+ const hostRaw = headersList.get("x-forwarded-host") ?? headersList.get("host");
177
+ const host = hostRaw?.split(",")[0]?.trim();
178
+ if (!host) {
179
+ return null;
180
+ }
181
+ const protoRaw = headersList.get("x-forwarded-proto");
182
+ const protoFirst = protoRaw?.split(",")[0]?.trim().toLowerCase();
183
+ const proto = protoFirst === "http" || protoFirst === "https" ? protoFirst : options.preferHttpWhenMissingProto ? "http" : "https";
184
+ return `${proto}://${host}`;
185
+ }
186
+
113
187
  // src/utils/auth-cookies.ts
114
- var DEFAULT_AUTH_COOKIE_PREFIXES = [
188
+ var ATHENA_AUTH_COOKIE_PREFIXES = [
115
189
  "athena-auth",
116
190
  "__Secure-athena-auth",
117
191
  "better-auth",
118
192
  "__Secure-better-auth"
119
193
  ];
194
+ var DEFAULT_AUTH_COOKIE_PREFIXES = ATHENA_AUTH_COOKIE_PREFIXES;
120
195
  function extractCookieNames(cookieHeader) {
121
196
  const names = /* @__PURE__ */ new Set();
122
197
  for (const rawCookie of cookieHeader.split(";")) {
@@ -178,9 +253,11 @@ function clearAuthCookies(options = {}) {
178
253
  if (!cookieHeader?.trim()) {
179
254
  return [];
180
255
  }
181
- const prefixes = options.prefixes?.length ? options.prefixes : [...DEFAULT_AUTH_COOKIE_PREFIXES];
256
+ const prefixes = options.prefixes?.length ? options.prefixes : [...ATHENA_AUTH_COOKIE_PREFIXES];
182
257
  const cookieNames = extractCookieNames(cookieHeader);
183
- const namesToClear = cookieNames.filter((name) => prefixes.some((prefix) => name.startsWith(prefix)));
258
+ const namesToClear = cookieNames.filter(
259
+ (name) => prefixes.some((prefix) => name.startsWith(prefix))
260
+ );
184
261
  if (namesToClear.length === 0) {
185
262
  return [];
186
263
  }
@@ -196,6 +273,295 @@ function clearAuthCookies(options = {}) {
196
273
  return namesToClear;
197
274
  }
198
275
 
276
+ // src/cookies/session-cookie-detection.ts
277
+ var SESSION_COOKIE_PATTERNS = [
278
+ /(?:^|;\s*)(?:__Secure-)?better-auth\.session_token=/,
279
+ /(?:^|;\s*)(?:__Secure-)?better-auth-session_token=/,
280
+ /(?:^|;\s*)(?:__Secure-)?athena-auth\.session-token=/,
281
+ /(?:^|;\s*)(?:__Secure-)?athena-auth-session-token=/,
282
+ /(?:^|;\s*)(?:__Secure-)?athena-auth\.session_token=/,
283
+ /(?:^|;\s*)(?:__Secure-)?athena-auth-session_token=/
284
+ ];
285
+ function hasAuthSessionCookie(cookieHeader) {
286
+ if (!cookieHeader) {
287
+ return false;
288
+ }
289
+ return SESSION_COOKIE_PATTERNS.some((pattern) => pattern.test(cookieHeader));
290
+ }
291
+
292
+ // src/utils/athena-auth-url.ts
293
+ var ATHENA_AUTH_PATH = "/api/auth";
294
+ var LOCAL_DEV_ORIGIN = "http://localhost:3000";
295
+ var DEFAULT_ATHENA_AUTH_ORIGIN = "https://auth.athena-auth.com";
296
+ var DEFAULT_ATHENA_AUTH_UPSTREAM_URL = DEFAULT_ATHENA_AUTH_ORIGIN;
297
+ var ATHENA_AUTH_UPSTREAM_ENV_KEYS = [
298
+ "ATHENA_AUTH_UPSTREAM_URL",
299
+ "ATHENA_AUTH_URL",
300
+ "NEXT_PUBLIC_ATHENA_AUTH_UPSTREAM_URL",
301
+ "NEXT_PUBLIC_ATHENA_AUTH_URL"
302
+ ];
303
+ var ATHENA_AUTH_UPSTREAM_URL_ENV_NAMES = ATHENA_AUTH_UPSTREAM_ENV_KEYS;
304
+ var LEADING_SLASHES_REGEX = /^\/+/;
305
+ function stripTrailingSlashes(value) {
306
+ return value.replace(/\/+$/g, "");
307
+ }
308
+ function ensureLeadingSlash(value) {
309
+ return value.startsWith("/") ? value : `/${value}`;
310
+ }
311
+ function ensureAthenaAuthPath(pathname) {
312
+ const normalizedPath = stripTrailingSlashes(
313
+ ensureLeadingSlash(pathname.trim())
314
+ );
315
+ if (!normalizedPath || normalizedPath === "/") {
316
+ return ATHENA_AUTH_PATH;
317
+ }
318
+ if (normalizedPath.endsWith(ATHENA_AUTH_PATH)) {
319
+ return normalizedPath;
320
+ }
321
+ return `${normalizedPath}${ATHENA_AUTH_PATH}`;
322
+ }
323
+ function stripAthenaAuthPath(pathname) {
324
+ const normalizedPath = stripTrailingSlashes(
325
+ ensureLeadingSlash(pathname.trim())
326
+ );
327
+ if (!normalizedPath || normalizedPath === "/") {
328
+ return "/";
329
+ }
330
+ if (normalizedPath === ATHENA_AUTH_PATH) {
331
+ return "/";
332
+ }
333
+ if (normalizedPath.endsWith(ATHENA_AUTH_PATH)) {
334
+ const withoutAuthPath = normalizedPath.slice(0, -ATHENA_AUTH_PATH.length);
335
+ return withoutAuthPath ? ensureLeadingSlash(withoutAuthPath) : "/";
336
+ }
337
+ return normalizedPath;
338
+ }
339
+ function readProcessEnv2() {
340
+ try {
341
+ const maybeProcess = globalThis.process;
342
+ return maybeProcess?.env;
343
+ } catch {
344
+ return void 0;
345
+ }
346
+ }
347
+ function getBrowserOrigin() {
348
+ try {
349
+ const origin = globalThis.window?.location?.origin;
350
+ return typeof origin === "string" && origin.length > 0 ? origin : void 0;
351
+ } catch {
352
+ return void 0;
353
+ }
354
+ }
355
+ function isAbsoluteUrl(value) {
356
+ const trimmed = value.trim();
357
+ return trimmed.startsWith("http://") || trimmed.startsWith("https://");
358
+ }
359
+ function readAthenaAuthUpstreamUrlFromEnv(env) {
360
+ for (const key of ATHENA_AUTH_UPSTREAM_ENV_KEYS) {
361
+ const value = env[key]?.trim();
362
+ if (value) {
363
+ return value;
364
+ }
365
+ }
366
+ return void 0;
367
+ }
368
+ function resolveConfiguredAthenaAuthUpstreamUrl(rawUpstreamUrl) {
369
+ if (typeof rawUpstreamUrl === "string") {
370
+ const trimmed = rawUpstreamUrl.trim();
371
+ return trimmed || void 0;
372
+ }
373
+ if (rawUpstreamUrl) {
374
+ return readAthenaAuthUpstreamUrlFromEnv(rawUpstreamUrl);
375
+ }
376
+ const processEnv = readProcessEnv2();
377
+ return processEnv ? readAthenaAuthUpstreamUrlFromEnv(processEnv) : void 0;
378
+ }
379
+ function normalizeAthenaAuthBaseUrl(urlOrPath) {
380
+ const trimmed = urlOrPath.trim();
381
+ if (!trimmed) {
382
+ return ATHENA_AUTH_PATH;
383
+ }
384
+ if (isAbsoluteUrl(trimmed)) {
385
+ const url = new URL(trimmed);
386
+ url.pathname = ensureAthenaAuthPath(url.pathname);
387
+ url.search = "";
388
+ url.hash = "";
389
+ return stripTrailingSlashes(url.toString());
390
+ }
391
+ return ensureAthenaAuthPath(trimmed);
392
+ }
393
+ function resolveAthenaAuthUpstreamUrl(rawUpstreamUrl) {
394
+ const configuredUpstream = resolveConfiguredAthenaAuthUpstreamUrl(rawUpstreamUrl) || DEFAULT_ATHENA_AUTH_ORIGIN;
395
+ if (isAbsoluteUrl(configuredUpstream)) {
396
+ const upstreamUrl = new URL(configuredUpstream);
397
+ upstreamUrl.pathname = stripAthenaAuthPath(upstreamUrl.pathname);
398
+ upstreamUrl.search = "";
399
+ upstreamUrl.hash = "";
400
+ return stripTrailingSlashes(upstreamUrl.toString());
401
+ }
402
+ const normalizedPath = stripAthenaAuthPath(configuredUpstream);
403
+ return stripTrailingSlashes(
404
+ new URL(normalizedPath, LOCAL_DEV_ORIGIN).toString()
405
+ );
406
+ }
407
+ function resolveBrowserFacingOrigin(rawUpstreamUrl) {
408
+ if (resolveConfiguredAthenaAuthUpstreamUrl(rawUpstreamUrl)) {
409
+ return `${resolveAthenaAuthUpstreamUrl(rawUpstreamUrl)}/`;
410
+ }
411
+ const browserOrigin = getBrowserOrigin();
412
+ if (browserOrigin) {
413
+ return `${browserOrigin}/`;
414
+ }
415
+ return `${LOCAL_DEV_ORIGIN}/`;
416
+ }
417
+ function resolvePreservedAthenaAuthBaseUrl(configuredAuthBaseUrl, rawUpstreamUrl) {
418
+ const trimmed = configuredAuthBaseUrl.trim();
419
+ const preservedConfiguredBaseUrl = trimmed || ATHENA_AUTH_PATH;
420
+ if (isAbsoluteUrl(preservedConfiguredBaseUrl)) {
421
+ return stripTrailingSlashes(preservedConfiguredBaseUrl);
422
+ }
423
+ return stripTrailingSlashes(
424
+ new URL(
425
+ ensureLeadingSlash(preservedConfiguredBaseUrl),
426
+ resolveBrowserFacingOrigin(rawUpstreamUrl)
427
+ ).toString()
428
+ );
429
+ }
430
+ function resolveAthenaAuthClientBaseUrl(configuredAuthBaseUrl, rawUpstreamUrl, options = {}) {
431
+ let baseInput;
432
+ if (typeof configuredAuthBaseUrl === "string") {
433
+ baseInput = configuredAuthBaseUrl;
434
+ } else if (configuredAuthBaseUrl) {
435
+ baseInput = readAthenaAuthUpstreamUrlFromEnv(configuredAuthBaseUrl) ?? ATHENA_AUTH_PATH;
436
+ } else {
437
+ const fromEnv = resolveConfiguredAthenaAuthUpstreamUrl(rawUpstreamUrl);
438
+ baseInput = fromEnv ?? ATHENA_AUTH_PATH;
439
+ }
440
+ if (options.appendAuthPath === false) {
441
+ return resolvePreservedAthenaAuthBaseUrl(baseInput, rawUpstreamUrl);
442
+ }
443
+ const normalizedConfiguredBaseUrl = normalizeAthenaAuthBaseUrl(baseInput);
444
+ if (isAbsoluteUrl(normalizedConfiguredBaseUrl)) {
445
+ return normalizedConfiguredBaseUrl;
446
+ }
447
+ const browserOrigin = getBrowserOrigin();
448
+ if (browserOrigin) {
449
+ return stripTrailingSlashes(
450
+ new URL(normalizedConfiguredBaseUrl, browserOrigin).toString()
451
+ );
452
+ }
453
+ if (resolveConfiguredAthenaAuthUpstreamUrl(rawUpstreamUrl)) {
454
+ const upstream = resolveAthenaAuthUpstreamUrl(rawUpstreamUrl);
455
+ return stripTrailingSlashes(
456
+ new URL(ATHENA_AUTH_PATH, `${upstream}/`).toString()
457
+ );
458
+ }
459
+ return stripTrailingSlashes(
460
+ new URL(normalizedConfiguredBaseUrl, LOCAL_DEV_ORIGIN).toString()
461
+ );
462
+ }
463
+ function resolveAthenaAuthRequestUrl(path, rawBaseUrl) {
464
+ const normalizedPath = path.replace(LEADING_SLASHES_REGEX, "");
465
+ const base = resolveAthenaAuthClientBaseUrl(rawBaseUrl);
466
+ return new URL(normalizedPath, `${base}/`).toString();
467
+ }
468
+ var ATHENA_AUTH_VERIFY_EMAIL_PATH = "verify-email";
469
+ var ATHENA_AUTH_GET_SESSION_PATH = "get-session";
470
+ var ATHENA_AUTH_GET_SESSION_ABSOLUTE_PATH = `${ATHENA_AUTH_PATH}/get-session`;
471
+ var AUTH_SESSION_PATH = ATHENA_AUTH_GET_SESSION_ABSOLUTE_PATH;
472
+ var ATHENA_AUTH_DISABLE_COOKIE_CACHE_QUERY_PARAM = "disableCookieCache";
473
+ var DISABLE_COOKIE_CACHE_QUERY_PARAM = ATHENA_AUTH_DISABLE_COOKIE_CACHE_QUERY_PARAM;
474
+ var ATHENA_AUTH_DISABLE_COOKIE_CACHE_QUERY_VALUE = "true";
475
+ var DISABLE_COOKIE_CACHE_QUERY_VALUE = ATHENA_AUTH_DISABLE_COOKIE_CACHE_QUERY_VALUE;
476
+ var ATHENA_SESSION_DATA_HEADER = "x-session-data";
477
+ var SESSION_DATA_HEADER = ATHENA_SESSION_DATA_HEADER;
478
+ function resolveEmailVerificationCallbackUrl(rawBaseUrl) {
479
+ return resolveAthenaAuthRequestUrl(ATHENA_AUTH_VERIFY_EMAIL_PATH, rawBaseUrl);
480
+ }
481
+ function createFreshSessionLookupUrl(baseUrl) {
482
+ const url = new URL(ATHENA_AUTH_GET_SESSION_ABSOLUTE_PATH, baseUrl);
483
+ url.searchParams.set(
484
+ ATHENA_AUTH_DISABLE_COOKIE_CACHE_QUERY_PARAM,
485
+ ATHENA_AUTH_DISABLE_COOKIE_CACHE_QUERY_VALUE
486
+ );
487
+ return url;
488
+ }
489
+
490
+ // src/utils/auth-routes.ts
491
+ var AUTH_DEFAULT_VIEW = "sign-in";
492
+ var AUTH_TWO_FACTOR_SEGMENT = "two-factor";
493
+ var AUTH_VIEW_BY_SEGMENT = {
494
+ "accept-invitation": "accept-invitation",
495
+ "check-email": "check-email",
496
+ "forget-password": "forgot-password",
497
+ "forgot-password": "forgot-password",
498
+ logout: "logout",
499
+ "reset-email-sent": "reset-email-sent",
500
+ "reset-password": "reset-password",
501
+ "sign-in": "sign-in",
502
+ "sign-up": "sign-up"
503
+ };
504
+ var AUTHENTICATED_REDIRECT_VIEW_SET = /* @__PURE__ */ new Set([
505
+ "sign-in",
506
+ "sign-up",
507
+ "forgot-password"
508
+ ]);
509
+ function resolveAuthViewFromSegment(segment) {
510
+ if (!segment) {
511
+ return AUTH_DEFAULT_VIEW;
512
+ }
513
+ return AUTH_VIEW_BY_SEGMENT[segment] ?? null;
514
+ }
515
+ function shouldRedirectAuthenticatedAuthView(view) {
516
+ return AUTHENTICATED_REDIRECT_VIEW_SET.has(view);
517
+ }
518
+ var AUTH_ROUTES = {
519
+ acceptInvitation: "/auth/accept-invitation",
520
+ appHome: "/",
521
+ checkEmail: "/auth/check-email",
522
+ forgotPassword: "/auth/forgot-password",
523
+ logout: "/auth/logout",
524
+ resetEmailSent: "/auth/reset-email-sent",
525
+ resetPassword: "/auth/reset-password",
526
+ signIn: "/auth/sign-in",
527
+ signUp: "/auth/sign-up",
528
+ socialCallback: "/auth/social-callback"
529
+ };
530
+ function createAuthRoutes(overrides = {}) {
531
+ return {
532
+ ...AUTH_ROUTES,
533
+ ...overrides
534
+ };
535
+ }
536
+ function createAuthModeRedirects(routes = AUTH_ROUTES) {
537
+ return {
538
+ "forgot-password": routes.forgotPassword,
539
+ login: routes.signIn,
540
+ logout: routes.logout,
541
+ "reset-password": routes.resetPassword,
542
+ signup: routes.signUp
543
+ };
544
+ }
545
+ var AUTH_MODE_REDIRECTS = createAuthModeRedirects();
546
+ var AUTH_MODE_SET = new Set(Object.keys(AUTH_MODE_REDIRECTS));
547
+ var AUTHENTICATED_REDIRECT_MODE_SET = /* @__PURE__ */ new Set([
548
+ "login",
549
+ "signup",
550
+ "forgot-password"
551
+ ]);
552
+ function isAuthMode(value) {
553
+ return AUTH_MODE_SET.has(value);
554
+ }
555
+ function shouldRedirectAuthenticatedAuthMode(mode) {
556
+ return AUTHENTICATED_REDIRECT_MODE_SET.has(mode);
557
+ }
558
+ function resolveAuthModeRedirect(mode, redirects = AUTH_MODE_REDIRECTS) {
559
+ if (!mode || !isAuthMode(mode)) {
560
+ return null;
561
+ }
562
+ return redirects[mode];
563
+ }
564
+
199
565
  // src/utils/proxy-request-headers.ts
200
566
  function proxyRequestHeaders(request) {
201
567
  const headers = new Headers(request.headers);
@@ -249,7 +615,7 @@ var getSessionCookie = (request, config) => {
249
615
 
250
616
  // src/utils/athena-request-headers.ts
251
617
  var NO_CACHE_HEADER_VALUE = "no-cache";
252
- var API_KEY_HEADER_CANDIDATES = ["x-api-key", "apikey"];
618
+ var API_KEY_HEADER_CANDIDATES = ["X-Athena-Key", "x-athena-key", "X-Api-Key", "x-api-key", "apikey"];
253
619
  var ATHENA_KEY_HEADER_CANDIDATES = ["X-Athena-Key", "x-athena-key"];
254
620
  var SESSION_TOKEN_HEADER_CANDIDATES = ["X-Athena-Auth-Session-Token"];
255
621
  var BEARER_MIRROR_HEADER_CANDIDATES = ["X-Athena-Auth-Bearer-Token"];
@@ -351,14 +717,6 @@ function buildServiceRequestHeaders(profile, sdkHeaderValue, config, options, ex
351
717
  });
352
718
  }
353
719
  function applyAthenaApiKeyHeaders(headers, apiKey, athenaKey) {
354
- if (apiKey) {
355
- if (!hasHeaderIgnoreCase(headers, "apikey")) {
356
- headers.apikey = apiKey;
357
- }
358
- if (!hasHeaderIgnoreCase(headers, "x-api-key")) {
359
- headers["x-api-key"] = apiKey;
360
- }
361
- }
362
720
  const resolvedAthenaKey = normalizeHeaderValue(athenaKey) ?? normalizeHeaderValue(apiKey);
363
721
  if (resolvedAthenaKey && !hasHeaderIgnoreCase(headers, "X-Athena-Key")) {
364
722
  headers["X-Athena-Key"] = resolvedAthenaKey;
@@ -418,6 +776,25 @@ function applyAthenaPgUriHeaders(headers, input) {
418
776
  }
419
777
  }
420
778
  }
779
+ function buildAthenaGatewayHeaders(input) {
780
+ const trimmedClientName = input.clientName?.trim();
781
+ const trimmedGatewayKey = input.gatewayKey?.trim();
782
+ const merged = {
783
+ ...trimmedClientName ? {
784
+ "X-Athena-Client": trimmedClientName
785
+ } : {},
786
+ ...trimmedGatewayKey ? {
787
+ "X-Api-Key": trimmedGatewayKey,
788
+ "X-Athena-Key": trimmedGatewayKey
789
+ } : {},
790
+ ...input.headers
791
+ };
792
+ return Object.fromEntries(
793
+ Object.entries(merged).flatMap(
794
+ ([key, value]) => typeof value === "string" && value.trim() ? [[key, value.trim()]] : []
795
+ )
796
+ );
797
+ }
421
798
  function buildAthenaRequestHeaders(input) {
422
799
  const forceNoCache = Boolean(input.forceNoCache);
423
800
  const mergedExtraHeaders = mergeExtraHeaders(input.configHeaders, input.callHeaders);
@@ -525,6 +902,6 @@ function sqlBigInt(value) {
525
902
  return `${BigInt(value).toString()}::bigint`;
526
903
  }
527
904
 
528
- export { applyAthenaApiKeyHeaders, applyAthenaAuthContextHeaders, applyAthenaPgUriHeaders, asBoolean, asBooleanOrNull, asIdentifier, asNumber, asRecord, asString, asStringArray, buildAthenaRequestHeaders, buildServiceRequestHeaders, clearAuthCookies, escapeLikePatternValue, firstString, hasHeaderIgnoreCase, isLocalHostname, parseBooleanFlag, proxyRequestHeaders, quoteSqlStringLiteral, readTrimmedString, resolveHeaderValue, resolveRequestHeaderOverrides, slugify, sqlBigInt, sqlJsonbLiteral, sqlNullableText, sqlText, trimTrailingSlashes };
905
+ export { ATHENA_AUTH_COOKIE_PREFIXES, ATHENA_AUTH_DISABLE_COOKIE_CACHE_QUERY_PARAM, ATHENA_AUTH_DISABLE_COOKIE_CACHE_QUERY_VALUE, ATHENA_AUTH_GET_SESSION_ABSOLUTE_PATH, ATHENA_AUTH_GET_SESSION_PATH, ATHENA_AUTH_PATH, ATHENA_AUTH_UPSTREAM_ENV_KEYS, ATHENA_AUTH_UPSTREAM_URL_ENV_NAMES, ATHENA_AUTH_VERIFY_EMAIL_PATH, ATHENA_SESSION_DATA_HEADER, AUTHENTICATED_REDIRECT_MODE_SET, AUTHENTICATED_REDIRECT_VIEW_SET, AUTH_DEFAULT_VIEW, AUTH_MODE_REDIRECTS, AUTH_MODE_SET, AUTH_ROUTES, AUTH_SESSION_PATH, AUTH_TWO_FACTOR_SEGMENT, AUTH_VIEW_BY_SEGMENT, DEFAULT_ATHENA_AUTH_ORIGIN, DEFAULT_ATHENA_AUTH_UPSTREAM_URL, DEFAULT_AUTH_COOKIE_PREFIXES, DISABLE_COOKIE_CACHE_QUERY_PARAM, DISABLE_COOKIE_CACHE_QUERY_VALUE, LOCAL_DEV_ORIGIN, SESSION_COOKIE_PATTERNS, SESSION_DATA_HEADER, applyAthenaApiKeyHeaders, applyAthenaAuthContextHeaders, applyAthenaPgUriHeaders, asBoolean, asBooleanOrNull, asIdentifier, asNonEmptyString, asNumber, asRecord, asString, asStringArray, buildAthenaGatewayHeaders, buildAthenaRequestHeaders, buildServiceRequestHeaders, clearAuthCookies, createAuthModeRedirects, createAuthRoutes, createFreshSessionLookupUrl, escapeLikePatternValue, firstString, getOriginFromHeaders, hasAuthSessionCookie, hasHeaderIgnoreCase, isAbsoluteUrl, isAuthMode, isDynamicServerUsageError, isLocalHostname, normalizeAthenaAuthBaseUrl, parseBooleanFlag, proxyRequestHeaders, quoteSqlStringLiteral, readAthenaAuthUpstreamUrlFromEnv, readEnv, readTrimmedString, requireEnv, resolveAthenaAuthClientBaseUrl, resolveAthenaAuthRequestUrl, resolveAthenaAuthUpstreamUrl, resolveAuthModeRedirect, resolveAuthViewFromSegment, resolveEmailVerificationCallbackUrl, resolveHeaderValue, resolveRequestHeaderOverrides, shouldRedirectAuthenticatedAuthMode, shouldRedirectAuthenticatedAuthView, slugify, sqlBigInt, sqlJsonbLiteral, sqlNullableText, sqlText, trimTrailingSlashes };
529
906
  //# sourceMappingURL=utils.js.map
530
907
  //# sourceMappingURL=utils.js.map