@xylex-group/athena 3.0.3 → 3.3.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 (86) hide show
  1. package/README.md +1 -1
  2. package/dist/admin.cjs +55 -1
  3. package/dist/admin.cjs.map +1 -1
  4. package/dist/admin.d.cts +32 -8
  5. package/dist/admin.d.ts +32 -8
  6. package/dist/admin.js +54 -2
  7. package/dist/admin.js.map +1 -1
  8. package/dist/athena-auth-url-C1FbVmN6.d.cts +200 -0
  9. package/dist/athena-auth-url-C1FbVmN6.d.ts +200 -0
  10. package/dist/{athena-request-headers-C7Jy-c_D.d.ts → athena-request-headers-DzimbvOA.d.ts} +48 -200
  11. package/dist/{athena-request-headers-DujFFyMU.d.cts → athena-request-headers-Lr_m8xCV.d.cts} +48 -200
  12. package/dist/billing.cjs +1 -1
  13. package/dist/billing.cjs.map +1 -1
  14. package/dist/billing.js +1 -1
  15. package/dist/billing.js.map +1 -1
  16. package/dist/browser.cjs +912 -5
  17. package/dist/browser.cjs.map +1 -1
  18. package/dist/browser.d.cts +8 -7
  19. package/dist/browser.d.ts +8 -7
  20. package/dist/browser.js +881 -6
  21. package/dist/browser.js.map +1 -1
  22. package/dist/cli/index.cjs +7909 -7061
  23. package/dist/cli/index.cjs.map +1 -1
  24. package/dist/cli/index.d.cts +17 -10
  25. package/dist/cli/index.d.ts +17 -10
  26. package/dist/cli/index.js +7911 -7063
  27. package/dist/cli/index.js.map +1 -1
  28. package/dist/env.cjs +130 -0
  29. package/dist/env.cjs.map +1 -0
  30. package/dist/env.d.cts +70 -0
  31. package/dist/env.d.ts +70 -0
  32. package/dist/env.js +122 -0
  33. package/dist/env.js.map +1 -0
  34. package/dist/index.cjs +1570 -98
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.cts +31 -8
  37. package/dist/index.d.ts +31 -8
  38. package/dist/index.js +1532 -100
  39. package/dist/index.js.map +1 -1
  40. package/dist/model-form-3Gr8rkdT.d.cts +281 -0
  41. package/dist/model-form-CotpEL7z.d.ts +281 -0
  42. package/dist/{module-CPG3ULxQ.d.cts → module-CQmOaDzP.d.cts} +4 -4
  43. package/dist/{module-BruTcxe0.d.ts → module-CWkUTcUc.d.ts} +4 -4
  44. package/dist/next/client.cjs +123 -7
  45. package/dist/next/client.cjs.map +1 -1
  46. package/dist/next/client.d.cts +4 -3
  47. package/dist/next/client.d.ts +4 -3
  48. package/dist/next/client.js +123 -7
  49. package/dist/next/client.js.map +1 -1
  50. package/dist/next/server.cjs +1130 -364
  51. package/dist/next/server.cjs.map +1 -1
  52. package/dist/next/server.d.cts +121 -8
  53. package/dist/next/server.d.ts +121 -8
  54. package/dist/next/server.js +1120 -365
  55. package/dist/next/server.js.map +1 -1
  56. package/dist/pipeline-BnRKO_Pd.d.cts +93 -0
  57. package/dist/pipeline-sWCmlFqu.d.ts +93 -0
  58. package/dist/{proxy-request-headers-m4D2Tduy.d.ts → proxy-request-headers-CttlcuRb.d.ts} +1 -1
  59. package/dist/{proxy-request-headers-DGxdoyA0.d.cts → proxy-request-headers-pIBSn1Fw.d.cts} +1 -1
  60. package/dist/react.cjs +672 -16
  61. package/dist/react.cjs.map +1 -1
  62. package/dist/react.d.cts +123 -8
  63. package/dist/react.d.ts +123 -8
  64. package/dist/react.js +671 -17
  65. package/dist/react.js.map +1 -1
  66. package/dist/schema-handlers-BtT_IQFi.d.cts +138 -0
  67. package/dist/schema-handlers-VjFDhIMw.d.ts +138 -0
  68. package/dist/social-providers.d.cts +1 -1
  69. package/dist/social-providers.d.ts +1 -1
  70. package/dist/{types-D6tZ9aoq.d.ts → types-BDX8zS7w.d.ts} +40 -1
  71. package/dist/{types-AOY-GLu8.d.cts → types-BVKpQmfY.d.cts} +11 -0
  72. package/dist/{types-AOY-GLu8.d.ts → types-BVKpQmfY.d.ts} +11 -0
  73. package/dist/{types-DFr2cL1N.d.cts → types-D-Am7YSd.d.cts} +40 -1
  74. package/dist/utils.cjs +30 -0
  75. package/dist/utils.cjs.map +1 -1
  76. package/dist/utils.d.cts +3 -2
  77. package/dist/utils.d.ts +3 -2
  78. package/dist/utils.js +30 -1
  79. package/dist/utils.js.map +1 -1
  80. package/dist/{v3-client-CWfZHcKL.d.cts → v3-client-G1SLeHRa.d.cts} +23 -1
  81. package/dist/{v3-client-DZp2NEhK.d.ts → v3-client-ao8BWQ8v.d.ts} +23 -1
  82. package/package.json +16 -2
  83. package/dist/model-form-Dh0sisdL.d.ts +0 -97
  84. package/dist/model-form-oOAJUVd4.d.cts +0 -97
  85. package/dist/pipeline-CIzV9f7b.d.cts +0 -8
  86. package/dist/pipeline-DNlc8Ayn.d.ts +0 -8
@@ -1799,7 +1799,7 @@ function buildAthenaGatewayUrl(baseUrl, path) {
1799
1799
 
1800
1800
  // package.json
1801
1801
  var package_default = {
1802
- version: "3.0.3"
1802
+ version: "3.3.0"
1803
1803
  };
1804
1804
 
1805
1805
  // src/sdk-version.ts
@@ -3901,6 +3901,14 @@ function createAuthModule(config = {}, runtimeOptions = {}) {
3901
3901
  changeEmailVerify: (input, options) => getWithQuery("/change-email/verify", input, options),
3902
3902
  deleteUserVerify: (input, options) => getWithQuery("/delete-user/verify", input, options),
3903
3903
  changePassword: (input, options) => postGeneric("/change-password", input, options),
3904
+ // Better Auth UI flat method aliases (also nested under session/account/social/user).
3905
+ listSessions: (input, options) => getGeneric("/list-sessions", input, options),
3906
+ revokeSession: sessionRevokeBinding,
3907
+ revokeOtherSessions,
3908
+ listAccounts: (input, options) => getGeneric("/list-accounts", input, options),
3909
+ unlinkAccount: (input, options) => postGeneric("/unlink-account", input, options),
3910
+ linkSocial: (input, options) => postGeneric("/link-social", input, options),
3911
+ updateUser: (input, options) => postGeneric("/update-user", input, options),
3904
3912
  user: {
3905
3913
  update: (input, options) => postGeneric("/update-user", input, options),
3906
3914
  delete: (input, options) => postGeneric("/delete-user", input, options),
@@ -9550,6 +9558,82 @@ var AthenaConfigurationError = class extends Error {
9550
9558
  }
9551
9559
  };
9552
9560
 
9561
+ // src/diagnostics.ts
9562
+ function readProcessEnv2() {
9563
+ try {
9564
+ return globalThis.process?.env ?? {};
9565
+ } catch {
9566
+ return {};
9567
+ }
9568
+ }
9569
+ function isTruthyEnv(value) {
9570
+ if (!value) return false;
9571
+ const normalized = value.trim().toLowerCase();
9572
+ return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on";
9573
+ }
9574
+ function isQuietAthenaDiagnosticsEnvironment(env = readProcessEnv2()) {
9575
+ const nodeEnv = env.NODE_ENV?.trim().toLowerCase();
9576
+ if (nodeEnv === "production") {
9577
+ return true;
9578
+ }
9579
+ if (isTruthyEnv(env.OPENNEXT_BUILD)) {
9580
+ return true;
9581
+ }
9582
+ const nextPhase = env.NEXT_PHASE?.trim();
9583
+ if (nextPhase === "phase-production-build") {
9584
+ return true;
9585
+ }
9586
+ if (isTruthyEnv(env.CI) && nodeEnv !== "test") {
9587
+ if (nodeEnv === "production" || isTruthyEnv(env.OPENNEXT_BUILD)) {
9588
+ return true;
9589
+ }
9590
+ }
9591
+ return false;
9592
+ }
9593
+ function resolveBooleanFlag(explicit, mode, quiet) {
9594
+ if (typeof explicit === "boolean") {
9595
+ return explicit;
9596
+ }
9597
+ if (mode === true) {
9598
+ return true;
9599
+ }
9600
+ if (mode === false) {
9601
+ return false;
9602
+ }
9603
+ if (mode === "auto") {
9604
+ return false;
9605
+ }
9606
+ return false;
9607
+ }
9608
+ function resolveAthenaClientDiagnostics(input) {
9609
+ const env = input.env ?? readProcessEnv2();
9610
+ const quiet = isQuietAthenaDiagnosticsEnvironment(env);
9611
+ const mode = input.diagnostics;
9612
+ const effectiveMode = mode === "auto" && quiet ? false : mode;
9613
+ const debugAst = resolveBooleanFlag(input.debugAst, effectiveMode);
9614
+ const findManyAst = resolveBooleanFlag(input.findManyAst, effectiveMode);
9615
+ let traceQueries;
9616
+ if (input.traceQueries !== void 0) {
9617
+ if (typeof input.traceQueries === "boolean") {
9618
+ traceQueries = input.traceQueries;
9619
+ } else if (effectiveMode === false || mode === "auto" && quiet) {
9620
+ const enabled = input.traceQueries.enabled;
9621
+ traceQueries = typeof enabled === "boolean" ? enabled ? input.traceQueries : false : false;
9622
+ } else {
9623
+ traceQueries = input.traceQueries;
9624
+ }
9625
+ } else if (effectiveMode === true) {
9626
+ traceQueries = true;
9627
+ } else {
9628
+ traceQueries = false;
9629
+ }
9630
+ return {
9631
+ debugAst,
9632
+ findManyAst,
9633
+ traceQueries
9634
+ };
9635
+ }
9636
+
9553
9637
  // src/v3-client.ts
9554
9638
  var ENV_URL_KEYS = ["ATHENA_URL", "NEXT_PUBLIC_ATHENA_URL"];
9555
9639
  var ENV_DB_URL_KEYS = ["ATHENA_DB_URL", "ATHENA_GATEWAY_URL", "NEXT_PUBLIC_ATHENA_DB_API_URL"];
@@ -9558,7 +9642,13 @@ var ENV_CHAT_URL_KEYS = ["ATHENA_CHAT_URL", "NEXT_PUBLIC_ATHENA_CHAT_URL"];
9558
9642
  var ENV_CHAT_WS_URL_KEYS = ["ATHENA_CHAT_WS_URL", "NEXT_PUBLIC_ATHENA_CHAT_WS_URL"];
9559
9643
  var ENV_STORAGE_URL_KEYS = ["ATHENA_STORAGE_URL", "NEXT_PUBLIC_ATHENA_STORAGE_URL"];
9560
9644
  var ENV_KEY_KEYS = ["ATHENA_API_KEY", "NEXT_PUBLIC_ATHENA_API_KEY", "ATHENA_GATEWAY_API_KEY", "X_API_KEY"];
9561
- var ENV_CLIENT_KEYS = ["ATHENA_CLIENT", "NEXT_PUBLIC_ATHENA_CLIENT"];
9645
+ var ENV_CLIENT_KEYS = [
9646
+ "ATHENA_CLIENT",
9647
+ "ATHENA_GATEWAY_CLIENT",
9648
+ "ATHENA_GENERATOR_CLIENT",
9649
+ "NEXT_PUBLIC_ATHENA_CLIENT",
9650
+ "NEXT_PUBLIC_ATHENA_GATEWAY_CLIENT"
9651
+ ];
9562
9652
  var MISSING_DB_SENTINEL = "https://athena.invalid/db";
9563
9653
  function readFirstEnv(env, keys) {
9564
9654
  for (const key of keys) {
@@ -9633,6 +9723,13 @@ function createInternalConfig(core) {
9633
9723
  const { config, urls } = core;
9634
9724
  const { url: _authUrl, ...authOptions } = config.auth ?? {};
9635
9725
  const { url: _storageUrl, directUpload, ...storageOptions } = config.storage ?? {};
9726
+ const diagnostics = resolveAthenaClientDiagnostics({
9727
+ diagnostics: config.diagnostics,
9728
+ debugAst: config.debugAst,
9729
+ findManyAst: config.findManyAst,
9730
+ traceQueries: config.traceQueries,
9731
+ env: config.env
9732
+ });
9636
9733
  return {
9637
9734
  baseUrl: urls.db ?? MISSING_DB_SENTINEL,
9638
9735
  apiKey: core.key,
@@ -9649,9 +9746,9 @@ function createInternalConfig(core) {
9649
9746
  models: config.models,
9650
9747
  behavior: {
9651
9748
  retryReads: config.retryReads,
9652
- traceQueries: config.traceQueries,
9653
- debugAst: config.debugAst,
9654
- findManyAst: config.findManyAst
9749
+ traceQueries: diagnostics.traceQueries,
9750
+ debugAst: diagnostics.debugAst,
9751
+ findManyAst: diagnostics.findManyAst
9655
9752
  },
9656
9753
  storage: {
9657
9754
  ...storageOptions,
@@ -9725,11 +9822,30 @@ function createClientView(core, viewContext) {
9725
9822
  return resolved.verifyConnection(options);
9726
9823
  },
9727
9824
  withContext(context) {
9825
+ warnIfEmptyRequestContext(context);
9728
9826
  return createClientView(core, mergeAthenaRequestContexts(viewContext, context));
9729
9827
  }
9730
9828
  };
9731
9829
  return Object.freeze(client);
9732
9830
  }
9831
+ function isEmptyAthenaRequestContext(context) {
9832
+ if (!context) return true;
9833
+ const hasHeaders = context.headers != null && Object.keys(context.headers).length > 0;
9834
+ return context.userId == null && context.organizationId == null && !normalizeOptionalContextString(context.cookie) && !normalizeOptionalContextString(context.bearerToken) && !normalizeOptionalContextString(context.sessionToken) && !context.forceNoCache && !hasHeaders;
9835
+ }
9836
+ function normalizeOptionalContextString(value) {
9837
+ const trimmed = value?.trim();
9838
+ return trimmed || void 0;
9839
+ }
9840
+ function warnIfEmptyRequestContext(context) {
9841
+ if (!isEmptyAthenaRequestContext(context)) return;
9842
+ if (typeof process !== "undefined" && process.env?.NODE_ENV === "production") {
9843
+ return;
9844
+ }
9845
+ console.warn(
9846
+ "[athena] withContext({}) has no userId, organizationId, cookie, bearerToken, sessionToken, headers, or forceNoCache. Gateway scope headers will not change. Pass identity fields, or use createAthenaServerClient({ session, scope })."
9847
+ );
9848
+ }
9733
9849
  function createClient(config) {
9734
9850
  return createClientView(resolveCore(config));
9735
9851
  }
@@ -9799,303 +9915,139 @@ async function resolveNextRequestContext(options = {}) {
9799
9915
  };
9800
9916
  }
9801
9917
 
9802
- // src/next/session-bridge/constants.ts
9803
- var ATHENA_AUTH_SESSION_BRIDGE_ROUTE = "/api/athena-auth/session";
9804
- var ATHENA_AUTH_SESSION_COOKIE_NAME = "athena-auth.session-token";
9805
- var ATHENA_AUTH_SESSION_COOKIE_NAMES = [
9806
- ATHENA_AUTH_SESSION_COOKIE_NAME,
9807
- "athena-auth.session_token"
9808
- ];
9809
-
9810
- // src/next/session-bridge/client.ts
9811
- var JSON_CONTENT_TYPE = "application/json";
9812
- function isBrowserRuntime() {
9813
- return typeof globalThis !== "undefined" && "window" in globalThis;
9814
- }
9815
- async function persistAthenaAuthSessionOnAppHost(payload, options) {
9816
- if (!(payload && isBrowserRuntime())) {
9817
- return;
9918
+ // src/organization/ensure-active-organization.ts
9919
+ function normalizeOrganizationId(value) {
9920
+ if (typeof value !== "string") {
9921
+ return null;
9818
9922
  }
9819
- const route = options?.route ?? ATHENA_AUTH_SESSION_BRIDGE_ROUTE;
9820
- const fetchImpl = options?.fetch ?? fetch;
9821
- const response = await fetchImpl(route, {
9822
- body: JSON.stringify(payload),
9823
- credentials: "same-origin",
9824
- headers: {
9825
- "Content-Type": JSON_CONTENT_TYPE
9826
- },
9827
- method: "POST"
9828
- });
9829
- if (!response.ok) {
9830
- throw new Error("Failed to persist the Athena Auth session on the app host");
9923
+ const normalized = value.trim();
9924
+ return normalized.length > 0 ? normalized : null;
9925
+ }
9926
+ function defaultSelectOrganizationId(organizations) {
9927
+ for (const organization of organizations) {
9928
+ const id = normalizeOrganizationId(organization.id);
9929
+ if (id) {
9930
+ return id;
9931
+ }
9831
9932
  }
9933
+ return null;
9832
9934
  }
9833
- async function clearAthenaAuthSessionOnAppHost(options) {
9834
- if (!isBrowserRuntime()) {
9835
- return;
9935
+ async function ensureActiveOrganization(options) {
9936
+ const currentActiveOrganizationId = normalizeOrganizationId(
9937
+ options.session?.session?.activeOrganizationId
9938
+ );
9939
+ if (currentActiveOrganizationId) {
9940
+ return {
9941
+ activeOrganizationId: currentActiveOrganizationId,
9942
+ didSetActiveOrganization: false
9943
+ };
9836
9944
  }
9837
- const route = options?.route ?? ATHENA_AUTH_SESSION_BRIDGE_ROUTE;
9838
- const fetchImpl = options?.fetch ?? fetch;
9839
- const response = await fetchImpl(route, {
9840
- credentials: "same-origin",
9841
- method: "DELETE"
9842
- });
9843
- if (!response.ok) {
9844
- throw new Error("Failed to clear the Athena Auth session on the app host");
9945
+ let organizations;
9946
+ try {
9947
+ organizations = await options.listOrganizations();
9948
+ } catch (error) {
9949
+ options.onError?.(error);
9950
+ return {
9951
+ activeOrganizationId: null,
9952
+ didSetActiveOrganization: false
9953
+ };
9954
+ }
9955
+ if (organizations.length === 0) {
9956
+ return {
9957
+ activeOrganizationId: null,
9958
+ didSetActiveOrganization: false
9959
+ };
9960
+ }
9961
+ const selectedOrganizationId = normalizeOrganizationId(
9962
+ (options.selectOrganizationId ?? defaultSelectOrganizationId)(organizations)
9963
+ );
9964
+ if (!selectedOrganizationId) {
9965
+ return {
9966
+ activeOrganizationId: null,
9967
+ didSetActiveOrganization: false
9968
+ };
9969
+ }
9970
+ try {
9971
+ await options.setActiveOrganization(selectedOrganizationId);
9972
+ return {
9973
+ activeOrganizationId: selectedOrganizationId,
9974
+ didSetActiveOrganization: true
9975
+ };
9976
+ } catch (error) {
9977
+ options.onError?.(error);
9978
+ return {
9979
+ activeOrganizationId: null,
9980
+ didSetActiveOrganization: false
9981
+ };
9845
9982
  }
9846
9983
  }
9847
9984
 
9848
- // src/next/session-bridge/payload.ts
9849
- function resolveSessionBridgePayload(payload) {
9850
- const token = payload?.session?.token ?? payload?.token;
9851
- if (typeof token !== "string") {
9852
- return null;
9985
+ // src/utils/athena-auth-url.ts
9986
+ var ATHENA_AUTH_PATH = "/api/auth";
9987
+ var LOCAL_DEV_ORIGIN = "http://localhost:3000";
9988
+ var DEFAULT_ATHENA_AUTH_ORIGIN = "https://auth.athena-auth.com";
9989
+ var DEFAULT_ATHENA_AUTH_UPSTREAM_URL = DEFAULT_ATHENA_AUTH_ORIGIN;
9990
+ var ATHENA_AUTH_UPSTREAM_ENV_KEYS = [
9991
+ "ATHENA_AUTH_UPSTREAM_URL",
9992
+ "ATHENA_AUTH_URL",
9993
+ "NEXT_PUBLIC_ATHENA_AUTH_UPSTREAM_URL",
9994
+ "NEXT_PUBLIC_ATHENA_AUTH_URL"
9995
+ ];
9996
+ var ATHENA_AUTH_UPSTREAM_URL_ENV_NAMES = ATHENA_AUTH_UPSTREAM_ENV_KEYS;
9997
+ var LEADING_SLASHES_REGEX = /^\/+/;
9998
+ function stripTrailingSlashes(value) {
9999
+ return value.replace(/\/+$/g, "");
10000
+ }
10001
+ function ensureLeadingSlash(value) {
10002
+ return value.startsWith("/") ? value : `/${value}`;
10003
+ }
10004
+ function ensureAthenaAuthPath(pathname) {
10005
+ const normalizedPath = stripTrailingSlashes(
10006
+ ensureLeadingSlash(pathname.trim())
10007
+ );
10008
+ if (!normalizedPath || normalizedPath === "/") {
10009
+ return ATHENA_AUTH_PATH;
9853
10010
  }
9854
- const normalizedToken = token.trim();
9855
- if (!normalizedToken) {
9856
- return null;
10011
+ if (normalizedPath.endsWith(ATHENA_AUTH_PATH)) {
10012
+ return normalizedPath;
9857
10013
  }
9858
- return {
9859
- token: normalizedToken,
9860
- expiresAt: typeof payload?.session?.expiresAt === "string" ? payload.session.expiresAt : void 0
9861
- };
10014
+ return `${normalizedPath}${ATHENA_AUTH_PATH}`;
9862
10015
  }
9863
-
9864
- // src/next/session-bridge/cookie.ts
9865
- var EXPIRED_AT = /* @__PURE__ */ new Date(0);
9866
- function resolveRequestIsSecure(request2) {
9867
- const forwardedProto = request2.headers.get("x-forwarded-proto")?.trim();
9868
- if (forwardedProto) {
9869
- const first = forwardedProto.split(",")[0]?.trim().toLowerCase();
9870
- if (first === "https") return true;
9871
- if (first === "http") return false;
10016
+ function stripAthenaAuthPath(pathname) {
10017
+ const normalizedPath = stripTrailingSlashes(
10018
+ ensureLeadingSlash(pathname.trim())
10019
+ );
10020
+ if (!normalizedPath || normalizedPath === "/") {
10021
+ return "/";
9872
10022
  }
9873
- return new URL(request2.url).protocol === "https:";
10023
+ if (normalizedPath === ATHENA_AUTH_PATH) {
10024
+ return "/";
10025
+ }
10026
+ if (normalizedPath.endsWith(ATHENA_AUTH_PATH)) {
10027
+ const withoutAuthPath = normalizedPath.slice(0, -ATHENA_AUTH_PATH.length);
10028
+ return withoutAuthPath ? ensureLeadingSlash(withoutAuthPath) : "/";
10029
+ }
10030
+ return normalizedPath;
9874
10031
  }
9875
- function resolveSessionCookieExpiresAt(value) {
9876
- if (typeof value !== "string") {
10032
+ function readProcessEnv3() {
10033
+ try {
10034
+ const maybeProcess = globalThis.process;
10035
+ return maybeProcess?.env;
10036
+ } catch {
9877
10037
  return void 0;
9878
10038
  }
9879
- const expiresAt = new Date(value);
9880
- return Number.isNaN(expiresAt.getTime()) ? void 0 : expiresAt;
9881
10039
  }
9882
- function serializeCookie(name, value, options) {
9883
- const parts = [
9884
- `${encodeURIComponent(name)}=${encodeURIComponent(value)}`,
9885
- `Path=${options.path}`,
9886
- "HttpOnly",
9887
- `SameSite=${options.sameSite === "none" ? "None" : options.sameSite === "strict" ? "Strict" : "Lax"}`
9888
- ];
9889
- if (options.secure) {
9890
- parts.push("Secure");
9891
- }
9892
- if (options.expires) {
9893
- parts.push(`Expires=${options.expires.toUTCString()}`);
10040
+ function getBrowserOrigin() {
10041
+ try {
10042
+ const origin = globalThis.window?.location?.origin;
10043
+ return typeof origin === "string" && origin.length > 0 ? origin : void 0;
10044
+ } catch {
10045
+ return void 0;
9894
10046
  }
9895
- return parts.join("; ");
9896
10047
  }
9897
- function resolveBridgeCookieConfig(options) {
9898
- return {
9899
- cookieName: options?.cookieName ?? ATHENA_AUTH_SESSION_COOKIE_NAME,
9900
- cookieNames: options?.cookieNames ?? ATHENA_AUTH_SESSION_COOKIE_NAMES,
9901
- cookiePath: options?.cookiePath ?? "/",
9902
- sameSite: options?.sameSite ?? "lax"
9903
- };
9904
- }
9905
- function appendSessionCookie(headers, request2, token, expiresAt, options) {
9906
- const config = resolveBridgeCookieConfig(options);
9907
- const secure = options?.secure ?? resolveRequestIsSecure(request2);
9908
- headers.append(
9909
- "set-cookie",
9910
- serializeCookie(config.cookieName, token, {
9911
- path: config.cookiePath,
9912
- sameSite: config.sameSite,
9913
- secure,
9914
- expires: expiresAt
9915
- })
9916
- );
9917
- }
9918
- function appendClearSessionCookies(headers, request2, options) {
9919
- const config = resolveBridgeCookieConfig(options);
9920
- const secure = options?.secure ?? resolveRequestIsSecure(request2);
9921
- const names = /* @__PURE__ */ new Set([config.cookieName, ...config.cookieNames]);
9922
- for (const name of names) {
9923
- headers.append(
9924
- "set-cookie",
9925
- serializeCookie(name, "", {
9926
- path: config.cookiePath,
9927
- sameSite: config.sameSite,
9928
- secure,
9929
- expires: EXPIRED_AT
9930
- })
9931
- );
9932
- }
9933
- }
9934
-
9935
- // src/next/session-bridge/handlers.ts
9936
- function json(body, init) {
9937
- const headers = init?.headers ?? new Headers();
9938
- if (!headers.has("content-type")) {
9939
- headers.set("content-type", "application/json; charset=utf-8");
9940
- }
9941
- return new Response(JSON.stringify(body), {
9942
- status: init?.status ?? 200,
9943
- headers
9944
- });
9945
- }
9946
- function resolveRoute(options) {
9947
- return options?.route ?? ATHENA_AUTH_SESSION_BRIDGE_ROUTE;
9948
- }
9949
- async function handleAthenaAuthSessionBridgePost(request2, options) {
9950
- const payload = await request2.json().catch(() => null);
9951
- const token = typeof payload?.token === "string" ? payload.token.trim() : "";
9952
- if (!token) {
9953
- return json(
9954
- {
9955
- error: "Missing Athena Auth session token"
9956
- },
9957
- { status: 400 }
9958
- );
9959
- }
9960
- const headers = new Headers();
9961
- appendSessionCookie(
9962
- headers,
9963
- request2,
9964
- token,
9965
- resolveSessionCookieExpiresAt(payload?.expiresAt),
9966
- options
9967
- );
9968
- return json(
9969
- {
9970
- ok: true,
9971
- route: resolveRoute(options)
9972
- },
9973
- { headers }
9974
- );
9975
- }
9976
- function handleAthenaAuthSessionBridgeDelete(request2, options) {
9977
- const headers = new Headers();
9978
- appendClearSessionCookies(headers, request2, options);
9979
- return json(
9980
- {
9981
- ok: true,
9982
- route: resolveRoute(options)
9983
- },
9984
- { headers }
9985
- );
9986
- }
9987
- function createAthenaAuthSessionBridgeHandlers(options) {
9988
- return {
9989
- POST: (request2) => handleAthenaAuthSessionBridgePost(request2, options),
9990
- DELETE: (request2) => handleAthenaAuthSessionBridgeDelete(request2, options)
9991
- };
9992
- }
9993
- function normalizePathname(pathname) {
9994
- if (pathname.length > 1 && pathname.endsWith("/")) {
9995
- return pathname.slice(0, -1);
9996
- }
9997
- return pathname || "/";
9998
- }
9999
- function isAthenaAuthSessionBridgePath(request2, options) {
10000
- const pathname = normalizePathname(new URL(request2.url).pathname);
10001
- const route = normalizePathname(resolveRoute(options));
10002
- if (pathname === route) {
10003
- return true;
10004
- }
10005
- const matchPaths = options?.matchPaths ?? ["session"];
10006
- const segments = pathname.split("/").filter(Boolean);
10007
- const tail = segments[segments.length - 1];
10008
- return typeof tail === "string" && matchPaths.includes(tail);
10009
- }
10010
- function createAthenaAuthSessionBridgePathHandlers(options) {
10011
- const notFound = () => json(
10012
- {
10013
- error: "Not found"
10014
- },
10015
- { status: 404 }
10016
- );
10017
- return {
10018
- POST: async (request2) => {
10019
- if (!isAthenaAuthSessionBridgePath(request2, options)) {
10020
- return notFound();
10021
- }
10022
- return handleAthenaAuthSessionBridgePost(request2, options);
10023
- },
10024
- DELETE: (request2) => {
10025
- if (!isAthenaAuthSessionBridgePath(request2, options)) {
10026
- return notFound();
10027
- }
10028
- return handleAthenaAuthSessionBridgeDelete(request2, options);
10029
- }
10030
- };
10031
- }
10032
-
10033
- // src/utils/athena-auth-url.ts
10034
- var ATHENA_AUTH_PATH = "/api/auth";
10035
- var LOCAL_DEV_ORIGIN = "http://localhost:3000";
10036
- var DEFAULT_ATHENA_AUTH_ORIGIN = "https://auth.athena-auth.com";
10037
- var DEFAULT_ATHENA_AUTH_UPSTREAM_URL = DEFAULT_ATHENA_AUTH_ORIGIN;
10038
- var ATHENA_AUTH_UPSTREAM_ENV_KEYS = [
10039
- "ATHENA_AUTH_UPSTREAM_URL",
10040
- "ATHENA_AUTH_URL",
10041
- "NEXT_PUBLIC_ATHENA_AUTH_UPSTREAM_URL",
10042
- "NEXT_PUBLIC_ATHENA_AUTH_URL"
10043
- ];
10044
- var ATHENA_AUTH_UPSTREAM_URL_ENV_NAMES = ATHENA_AUTH_UPSTREAM_ENV_KEYS;
10045
- var LEADING_SLASHES_REGEX = /^\/+/;
10046
- function stripTrailingSlashes(value) {
10047
- return value.replace(/\/+$/g, "");
10048
- }
10049
- function ensureLeadingSlash(value) {
10050
- return value.startsWith("/") ? value : `/${value}`;
10051
- }
10052
- function ensureAthenaAuthPath(pathname) {
10053
- const normalizedPath = stripTrailingSlashes(
10054
- ensureLeadingSlash(pathname.trim())
10055
- );
10056
- if (!normalizedPath || normalizedPath === "/") {
10057
- return ATHENA_AUTH_PATH;
10058
- }
10059
- if (normalizedPath.endsWith(ATHENA_AUTH_PATH)) {
10060
- return normalizedPath;
10061
- }
10062
- return `${normalizedPath}${ATHENA_AUTH_PATH}`;
10063
- }
10064
- function stripAthenaAuthPath(pathname) {
10065
- const normalizedPath = stripTrailingSlashes(
10066
- ensureLeadingSlash(pathname.trim())
10067
- );
10068
- if (!normalizedPath || normalizedPath === "/") {
10069
- return "/";
10070
- }
10071
- if (normalizedPath === ATHENA_AUTH_PATH) {
10072
- return "/";
10073
- }
10074
- if (normalizedPath.endsWith(ATHENA_AUTH_PATH)) {
10075
- const withoutAuthPath = normalizedPath.slice(0, -ATHENA_AUTH_PATH.length);
10076
- return withoutAuthPath ? ensureLeadingSlash(withoutAuthPath) : "/";
10077
- }
10078
- return normalizedPath;
10079
- }
10080
- function readProcessEnv2() {
10081
- try {
10082
- const maybeProcess = globalThis.process;
10083
- return maybeProcess?.env;
10084
- } catch {
10085
- return void 0;
10086
- }
10087
- }
10088
- function getBrowserOrigin() {
10089
- try {
10090
- const origin = globalThis.window?.location?.origin;
10091
- return typeof origin === "string" && origin.length > 0 ? origin : void 0;
10092
- } catch {
10093
- return void 0;
10094
- }
10095
- }
10096
- function isAbsoluteUrl(value) {
10097
- const trimmed = value.trim();
10098
- return trimmed.startsWith("http://") || trimmed.startsWith("https://");
10048
+ function isAbsoluteUrl(value) {
10049
+ const trimmed = value.trim();
10050
+ return trimmed.startsWith("http://") || trimmed.startsWith("https://");
10099
10051
  }
10100
10052
  function readAthenaAuthUpstreamUrlFromEnv(env) {
10101
10053
  for (const key of ATHENA_AUTH_UPSTREAM_ENV_KEYS) {
@@ -10114,7 +10066,7 @@ function resolveConfiguredAthenaAuthUpstreamUrl(rawUpstreamUrl) {
10114
10066
  if (rawUpstreamUrl) {
10115
10067
  return readAthenaAuthUpstreamUrlFromEnv(rawUpstreamUrl);
10116
10068
  }
10117
- const processEnv = readProcessEnv2();
10069
+ const processEnv = readProcessEnv3();
10118
10070
  return processEnv ? readAthenaAuthUpstreamUrlFromEnv(processEnv) : void 0;
10119
10071
  }
10120
10072
  function normalizeAthenaAuthBaseUrl(urlOrPath) {
@@ -10201,31 +10153,442 @@ function resolveAthenaAuthClientBaseUrl(configuredAuthBaseUrl, rawUpstreamUrl, o
10201
10153
  new URL(normalizedConfiguredBaseUrl, LOCAL_DEV_ORIGIN).toString()
10202
10154
  );
10203
10155
  }
10204
- function resolveAthenaAuthRequestUrl(path, rawBaseUrl) {
10205
- const normalizedPath = path.replace(LEADING_SLASHES_REGEX, "");
10206
- const base = resolveAthenaAuthClientBaseUrl(rawBaseUrl);
10207
- return new URL(normalizedPath, `${base}/`).toString();
10156
+ function resolveAthenaAuthRequestUrl(path, rawBaseUrl) {
10157
+ const normalizedPath = path.replace(LEADING_SLASHES_REGEX, "");
10158
+ const base = resolveAthenaAuthClientBaseUrl(rawBaseUrl);
10159
+ return new URL(normalizedPath, `${base}/`).toString();
10160
+ }
10161
+ var ATHENA_AUTH_VERIFY_EMAIL_PATH = "verify-email";
10162
+ var ATHENA_AUTH_GET_SESSION_PATH = "get-session";
10163
+ var ATHENA_AUTH_GET_SESSION_ABSOLUTE_PATH = `${ATHENA_AUTH_PATH}/get-session`;
10164
+ var AUTH_SESSION_PATH = ATHENA_AUTH_GET_SESSION_ABSOLUTE_PATH;
10165
+ var ATHENA_AUTH_DISABLE_COOKIE_CACHE_QUERY_PARAM = "disableCookieCache";
10166
+ var DISABLE_COOKIE_CACHE_QUERY_PARAM = ATHENA_AUTH_DISABLE_COOKIE_CACHE_QUERY_PARAM;
10167
+ var ATHENA_AUTH_DISABLE_COOKIE_CACHE_QUERY_VALUE = "true";
10168
+ var DISABLE_COOKIE_CACHE_QUERY_VALUE = ATHENA_AUTH_DISABLE_COOKIE_CACHE_QUERY_VALUE;
10169
+ var ATHENA_SESSION_DATA_HEADER = "x-session-data";
10170
+ var SESSION_DATA_HEADER = ATHENA_SESSION_DATA_HEADER;
10171
+ function resolveEmailVerificationCallbackUrl(rawBaseUrl) {
10172
+ return resolveAthenaAuthRequestUrl(ATHENA_AUTH_VERIFY_EMAIL_PATH, rawBaseUrl);
10173
+ }
10174
+ function createFreshSessionLookupUrl(baseUrl) {
10175
+ const url = new URL(ATHENA_AUTH_GET_SESSION_ABSOLUTE_PATH, baseUrl);
10176
+ url.searchParams.set(
10177
+ ATHENA_AUTH_DISABLE_COOKIE_CACHE_QUERY_PARAM,
10178
+ ATHENA_AUTH_DISABLE_COOKIE_CACHE_QUERY_VALUE
10179
+ );
10180
+ return url;
10181
+ }
10182
+
10183
+ // src/next/get-server-session.ts
10184
+ function normalizeId(value) {
10185
+ if (typeof value !== "string") return null;
10186
+ const trimmed = value.trim();
10187
+ return trimmed.length > 0 ? trimmed : null;
10188
+ }
10189
+ function readHeader2(headers, target) {
10190
+ if (!headers) return void 0;
10191
+ if (typeof headers.get === "function") {
10192
+ const value = headers.get(target);
10193
+ return value?.trim() || void 0;
10194
+ }
10195
+ const normalizedTarget = target.toLowerCase();
10196
+ for (const [key, value] of Object.entries(headers)) {
10197
+ if (key.toLowerCase() === normalizedTarget) {
10198
+ const normalized = value?.trim();
10199
+ return normalized || void 0;
10200
+ }
10201
+ }
10202
+ return void 0;
10203
+ }
10204
+ function parseAthenaSessionDataHeader(raw) {
10205
+ if (!raw?.trim()) return null;
10206
+ try {
10207
+ const parsed = JSON.parse(raw);
10208
+ return coerceSessionResponse(parsed);
10209
+ } catch {
10210
+ return null;
10211
+ }
10212
+ }
10213
+ function coerceSessionResponse(value) {
10214
+ if (!value || typeof value !== "object") return null;
10215
+ const record = value;
10216
+ const payload = record.session && record.user ? record : record.data && typeof record.data === "object" ? record.data : null;
10217
+ if (!payload) return null;
10218
+ const user = payload.user;
10219
+ const session = payload.session;
10220
+ if (!user || typeof user !== "object" || !session || typeof session !== "object") {
10221
+ return null;
10222
+ }
10223
+ const userRecord = user;
10224
+ const sessionRecord = session;
10225
+ const userId = normalizeId(
10226
+ typeof userRecord.id === "string" ? userRecord.id : void 0
10227
+ );
10228
+ const sessionId = normalizeId(
10229
+ typeof sessionRecord.id === "string" ? sessionRecord.id : void 0
10230
+ );
10231
+ if (!userId || !sessionId) return null;
10232
+ return {
10233
+ user: {
10234
+ id: userId,
10235
+ email: typeof userRecord.email === "string" ? userRecord.email : "",
10236
+ name: typeof userRecord.name === "string" ? userRecord.name : null,
10237
+ image: typeof userRecord.image === "string" ? userRecord.image : null,
10238
+ emailVerified: typeof userRecord.emailVerified === "boolean" ? userRecord.emailVerified : void 0,
10239
+ role: typeof userRecord.role === "string" ? userRecord.role : null,
10240
+ username: typeof userRecord.username === "string" ? userRecord.username : null
10241
+ },
10242
+ session: {
10243
+ id: sessionId,
10244
+ userId: typeof sessionRecord.userId === "string" ? sessionRecord.userId : userId,
10245
+ token: typeof sessionRecord.token === "string" ? sessionRecord.token : void 0,
10246
+ expiresAt: typeof sessionRecord.expiresAt === "string" ? sessionRecord.expiresAt : void 0,
10247
+ activeOrganizationId: normalizeId(
10248
+ typeof sessionRecord.activeOrganizationId === "string" ? sessionRecord.activeOrganizationId : null
10249
+ )
10250
+ }
10251
+ };
10252
+ }
10253
+ async function fetchSessionFromAuth(options) {
10254
+ const headers = {
10255
+ accept: "application/json"
10256
+ };
10257
+ if (options.cookie) headers.cookie = options.cookie;
10258
+ if (options.bearerToken) headers.authorization = `Bearer ${options.bearerToken}`;
10259
+ try {
10260
+ const response = await options.fetchImpl(options.url, {
10261
+ method: "GET",
10262
+ headers,
10263
+ cache: "no-store"
10264
+ });
10265
+ if (!response.ok) return null;
10266
+ const json3 = await response.json();
10267
+ return coerceSessionResponse(json3);
10268
+ } catch {
10269
+ return null;
10270
+ }
10271
+ }
10272
+ function resolveSessionLookupUrl(options) {
10273
+ if (options.authSessionUrl) {
10274
+ return String(options.authSessionUrl);
10275
+ }
10276
+ if (options.appOrigin) {
10277
+ return createFreshSessionLookupUrl(options.appOrigin).toString();
10278
+ }
10279
+ return null;
10280
+ }
10281
+ async function getServerSession(options = {}) {
10282
+ const fetchImpl = options.fetchImpl ?? globalThis.fetch.bind(globalThis);
10283
+ const skipWithoutCredentials = options.skipFetchWithoutCredentials !== false;
10284
+ const hasExplicitRequestInputs = options.requestHeaders !== void 0 || options.requestCookies !== void 0 || options.sessionDataHeader !== void 0;
10285
+ const requestHeaders = options.requestHeaders ?? (hasExplicitRequestInputs ? {} : void 0);
10286
+ const requestCookies = options.requestCookies ?? (hasExplicitRequestInputs ? "" : void 0);
10287
+ const request2 = await resolveNextRequestContext({
10288
+ requestHeaders,
10289
+ requestCookies,
10290
+ forceNoCache: options.forceNoCache,
10291
+ headers: options.headers
10292
+ });
10293
+ const headerRaw = options.sessionDataHeader !== void 0 ? options.sessionDataHeader : readHeader2(requestHeaders, ATHENA_SESSION_DATA_HEADER) ?? readHeader2(requestHeaders, "x-session-data");
10294
+ let fromSessionDataHeader = false;
10295
+ let session = parseAthenaSessionDataHeader(headerRaw);
10296
+ if (session) {
10297
+ fromSessionDataHeader = true;
10298
+ } else {
10299
+ const hasCredentials = Boolean(request2.cookie || request2.bearerToken);
10300
+ if (!skipWithoutCredentials || hasCredentials) {
10301
+ const lookupUrl = resolveSessionLookupUrl(options);
10302
+ if (lookupUrl) {
10303
+ session = await fetchSessionFromAuth({
10304
+ url: lookupUrl,
10305
+ cookie: request2.cookie,
10306
+ bearerToken: request2.bearerToken,
10307
+ fetchImpl
10308
+ });
10309
+ }
10310
+ }
10311
+ }
10312
+ if (!session) {
10313
+ return {
10314
+ session: null,
10315
+ userId: null,
10316
+ rawActiveOrganizationId: null,
10317
+ organizationId: null,
10318
+ didEnsureActiveOrganization: false,
10319
+ fromSessionDataHeader: false
10320
+ };
10321
+ }
10322
+ const userId = normalizeId(session.user?.id);
10323
+ const rawActiveOrganizationId = normalizeId(session.session?.activeOrganizationId);
10324
+ let organizationId = rawActiveOrganizationId;
10325
+ if (userId && options.resolveActiveOrganizationId) {
10326
+ organizationId = normalizeId(
10327
+ await options.resolveActiveOrganizationId({
10328
+ userId,
10329
+ rawActiveOrganizationId,
10330
+ session
10331
+ })
10332
+ );
10333
+ }
10334
+ let didEnsureActiveOrganization = false;
10335
+ if (options.ensureActiveOrganization && userId) {
10336
+ const sessionForEnsure = {
10337
+ session: {
10338
+ activeOrganizationId: organizationId
10339
+ }
10340
+ };
10341
+ const ensured = await ensureActiveOrganization({
10342
+ session: sessionForEnsure,
10343
+ listOrganizations: options.ensureActiveOrganization.listOrganizations,
10344
+ setActiveOrganization: options.ensureActiveOrganization.setActiveOrganization,
10345
+ selectOrganizationId: options.ensureActiveOrganization.selectOrganizationId,
10346
+ onError: options.ensureActiveOrganization.onError
10347
+ });
10348
+ didEnsureActiveOrganization = ensured.didSetActiveOrganization;
10349
+ if (ensured.activeOrganizationId) {
10350
+ organizationId = ensured.activeOrganizationId;
10351
+ }
10352
+ }
10353
+ return {
10354
+ session,
10355
+ userId,
10356
+ rawActiveOrganizationId,
10357
+ organizationId,
10358
+ didEnsureActiveOrganization,
10359
+ fromSessionDataHeader
10360
+ };
10361
+ }
10362
+
10363
+ // src/next/session-bridge/constants.ts
10364
+ var ATHENA_AUTH_SESSION_BRIDGE_ROUTE = "/api/athena-auth/session";
10365
+ var ATHENA_AUTH_SESSION_COOKIE_NAME = "athena-auth.session-token";
10366
+ var ATHENA_AUTH_SESSION_COOKIE_NAMES = [
10367
+ ATHENA_AUTH_SESSION_COOKIE_NAME,
10368
+ "athena-auth.session_token"
10369
+ ];
10370
+
10371
+ // src/next/session-bridge/client.ts
10372
+ var JSON_CONTENT_TYPE = "application/json";
10373
+ function isBrowserRuntime() {
10374
+ return typeof globalThis !== "undefined" && "window" in globalThis;
10375
+ }
10376
+ async function persistAthenaAuthSessionOnAppHost(payload, options) {
10377
+ if (!(payload && isBrowserRuntime())) {
10378
+ return;
10379
+ }
10380
+ const route = options?.route ?? ATHENA_AUTH_SESSION_BRIDGE_ROUTE;
10381
+ const fetchImpl = options?.fetch ?? fetch;
10382
+ const response = await fetchImpl(route, {
10383
+ body: JSON.stringify(payload),
10384
+ credentials: "same-origin",
10385
+ headers: {
10386
+ "Content-Type": JSON_CONTENT_TYPE
10387
+ },
10388
+ method: "POST"
10389
+ });
10390
+ if (!response.ok) {
10391
+ throw new Error("Failed to persist the Athena Auth session on the app host");
10392
+ }
10393
+ }
10394
+ async function clearAthenaAuthSessionOnAppHost(options) {
10395
+ if (!isBrowserRuntime()) {
10396
+ return;
10397
+ }
10398
+ const route = options?.route ?? ATHENA_AUTH_SESSION_BRIDGE_ROUTE;
10399
+ const fetchImpl = options?.fetch ?? fetch;
10400
+ const response = await fetchImpl(route, {
10401
+ credentials: "same-origin",
10402
+ method: "DELETE"
10403
+ });
10404
+ if (!response.ok) {
10405
+ throw new Error("Failed to clear the Athena Auth session on the app host");
10406
+ }
10407
+ }
10408
+
10409
+ // src/next/session-bridge/payload.ts
10410
+ function resolveSessionBridgePayload(payload) {
10411
+ const token = payload?.session?.token ?? payload?.token;
10412
+ if (typeof token !== "string") {
10413
+ return null;
10414
+ }
10415
+ const normalizedToken = token.trim();
10416
+ if (!normalizedToken) {
10417
+ return null;
10418
+ }
10419
+ return {
10420
+ token: normalizedToken,
10421
+ expiresAt: typeof payload?.session?.expiresAt === "string" ? payload.session.expiresAt : void 0
10422
+ };
10423
+ }
10424
+
10425
+ // src/next/session-bridge/cookie.ts
10426
+ var EXPIRED_AT = /* @__PURE__ */ new Date(0);
10427
+ function resolveRequestIsSecure(request2) {
10428
+ const forwardedProto = request2.headers.get("x-forwarded-proto")?.trim();
10429
+ if (forwardedProto) {
10430
+ const first = forwardedProto.split(",")[0]?.trim().toLowerCase();
10431
+ if (first === "https") return true;
10432
+ if (first === "http") return false;
10433
+ }
10434
+ return new URL(request2.url).protocol === "https:";
10435
+ }
10436
+ function resolveSessionCookieExpiresAt(value) {
10437
+ if (typeof value !== "string") {
10438
+ return void 0;
10439
+ }
10440
+ const expiresAt = new Date(value);
10441
+ return Number.isNaN(expiresAt.getTime()) ? void 0 : expiresAt;
10442
+ }
10443
+ function serializeCookie(name, value, options) {
10444
+ const parts = [
10445
+ `${encodeURIComponent(name)}=${encodeURIComponent(value)}`,
10446
+ `Path=${options.path}`,
10447
+ "HttpOnly",
10448
+ `SameSite=${options.sameSite === "none" ? "None" : options.sameSite === "strict" ? "Strict" : "Lax"}`
10449
+ ];
10450
+ if (options.secure) {
10451
+ parts.push("Secure");
10452
+ }
10453
+ if (options.expires) {
10454
+ parts.push(`Expires=${options.expires.toUTCString()}`);
10455
+ }
10456
+ return parts.join("; ");
10457
+ }
10458
+ function resolveBridgeCookieConfig(options) {
10459
+ return {
10460
+ cookieName: options?.cookieName ?? ATHENA_AUTH_SESSION_COOKIE_NAME,
10461
+ cookieNames: options?.cookieNames ?? ATHENA_AUTH_SESSION_COOKIE_NAMES,
10462
+ cookiePath: options?.cookiePath ?? "/",
10463
+ sameSite: options?.sameSite ?? "lax"
10464
+ };
10465
+ }
10466
+ function appendSessionCookie(headers, request2, token, expiresAt, options) {
10467
+ const config = resolveBridgeCookieConfig(options);
10468
+ const secure = options?.secure ?? resolveRequestIsSecure(request2);
10469
+ headers.append(
10470
+ "set-cookie",
10471
+ serializeCookie(config.cookieName, token, {
10472
+ path: config.cookiePath,
10473
+ sameSite: config.sameSite,
10474
+ secure,
10475
+ expires: expiresAt
10476
+ })
10477
+ );
10478
+ }
10479
+ function appendClearSessionCookies(headers, request2, options) {
10480
+ const config = resolveBridgeCookieConfig(options);
10481
+ const secure = options?.secure ?? resolveRequestIsSecure(request2);
10482
+ const names = /* @__PURE__ */ new Set([config.cookieName, ...config.cookieNames]);
10483
+ for (const name of names) {
10484
+ headers.append(
10485
+ "set-cookie",
10486
+ serializeCookie(name, "", {
10487
+ path: config.cookiePath,
10488
+ sameSite: config.sameSite,
10489
+ secure,
10490
+ expires: EXPIRED_AT
10491
+ })
10492
+ );
10493
+ }
10494
+ }
10495
+
10496
+ // src/next/session-bridge/handlers.ts
10497
+ function json(body, init) {
10498
+ const headers = init?.headers ?? new Headers();
10499
+ if (!headers.has("content-type")) {
10500
+ headers.set("content-type", "application/json; charset=utf-8");
10501
+ }
10502
+ return new Response(JSON.stringify(body), {
10503
+ status: init?.status ?? 200,
10504
+ headers
10505
+ });
10506
+ }
10507
+ function resolveRoute(options) {
10508
+ return options?.route ?? ATHENA_AUTH_SESSION_BRIDGE_ROUTE;
10509
+ }
10510
+ async function handleAthenaAuthSessionBridgePost(request2, options) {
10511
+ const payload = await request2.json().catch(() => null);
10512
+ const token = typeof payload?.token === "string" ? payload.token.trim() : "";
10513
+ if (!token) {
10514
+ return json(
10515
+ {
10516
+ error: "Missing Athena Auth session token"
10517
+ },
10518
+ { status: 400 }
10519
+ );
10520
+ }
10521
+ const headers = new Headers();
10522
+ appendSessionCookie(
10523
+ headers,
10524
+ request2,
10525
+ token,
10526
+ resolveSessionCookieExpiresAt(payload?.expiresAt),
10527
+ options
10528
+ );
10529
+ return json(
10530
+ {
10531
+ ok: true,
10532
+ route: resolveRoute(options)
10533
+ },
10534
+ { headers }
10535
+ );
10536
+ }
10537
+ function handleAthenaAuthSessionBridgeDelete(request2, options) {
10538
+ const headers = new Headers();
10539
+ appendClearSessionCookies(headers, request2, options);
10540
+ return json(
10541
+ {
10542
+ ok: true,
10543
+ route: resolveRoute(options)
10544
+ },
10545
+ { headers }
10546
+ );
10208
10547
  }
10209
- var ATHENA_AUTH_VERIFY_EMAIL_PATH = "verify-email";
10210
- var ATHENA_AUTH_GET_SESSION_PATH = "get-session";
10211
- var ATHENA_AUTH_GET_SESSION_ABSOLUTE_PATH = `${ATHENA_AUTH_PATH}/get-session`;
10212
- var AUTH_SESSION_PATH = ATHENA_AUTH_GET_SESSION_ABSOLUTE_PATH;
10213
- var ATHENA_AUTH_DISABLE_COOKIE_CACHE_QUERY_PARAM = "disableCookieCache";
10214
- var DISABLE_COOKIE_CACHE_QUERY_PARAM = ATHENA_AUTH_DISABLE_COOKIE_CACHE_QUERY_PARAM;
10215
- var ATHENA_AUTH_DISABLE_COOKIE_CACHE_QUERY_VALUE = "true";
10216
- var DISABLE_COOKIE_CACHE_QUERY_VALUE = ATHENA_AUTH_DISABLE_COOKIE_CACHE_QUERY_VALUE;
10217
- var ATHENA_SESSION_DATA_HEADER = "x-session-data";
10218
- var SESSION_DATA_HEADER = ATHENA_SESSION_DATA_HEADER;
10219
- function resolveEmailVerificationCallbackUrl(rawBaseUrl) {
10220
- return resolveAthenaAuthRequestUrl(ATHENA_AUTH_VERIFY_EMAIL_PATH, rawBaseUrl);
10548
+ function createAthenaAuthSessionBridgeHandlers(options) {
10549
+ return {
10550
+ POST: (request2) => handleAthenaAuthSessionBridgePost(request2, options),
10551
+ DELETE: (request2) => handleAthenaAuthSessionBridgeDelete(request2, options)
10552
+ };
10221
10553
  }
10222
- function createFreshSessionLookupUrl(baseUrl) {
10223
- const url = new URL(ATHENA_AUTH_GET_SESSION_ABSOLUTE_PATH, baseUrl);
10224
- url.searchParams.set(
10225
- ATHENA_AUTH_DISABLE_COOKIE_CACHE_QUERY_PARAM,
10226
- ATHENA_AUTH_DISABLE_COOKIE_CACHE_QUERY_VALUE
10554
+ function normalizePathname(pathname) {
10555
+ if (pathname.length > 1 && pathname.endsWith("/")) {
10556
+ return pathname.slice(0, -1);
10557
+ }
10558
+ return pathname || "/";
10559
+ }
10560
+ function isAthenaAuthSessionBridgePath(request2, options) {
10561
+ const pathname = normalizePathname(new URL(request2.url).pathname);
10562
+ const route = normalizePathname(resolveRoute(options));
10563
+ if (pathname === route) {
10564
+ return true;
10565
+ }
10566
+ const matchPaths = options?.matchPaths ?? ["session"];
10567
+ const segments = pathname.split("/").filter(Boolean);
10568
+ const tail = segments[segments.length - 1];
10569
+ return typeof tail === "string" && matchPaths.includes(tail);
10570
+ }
10571
+ function createAthenaAuthSessionBridgePathHandlers(options) {
10572
+ const notFound = () => json(
10573
+ {
10574
+ error: "Not found"
10575
+ },
10576
+ { status: 404 }
10227
10577
  );
10228
- return url;
10578
+ return {
10579
+ POST: async (request2) => {
10580
+ if (!isAthenaAuthSessionBridgePath(request2, options)) {
10581
+ return notFound();
10582
+ }
10583
+ return handleAthenaAuthSessionBridgePost(request2, options);
10584
+ },
10585
+ DELETE: (request2) => {
10586
+ if (!isAthenaAuthSessionBridgePath(request2, options)) {
10587
+ return notFound();
10588
+ }
10589
+ return handleAthenaAuthSessionBridgeDelete(request2, options);
10590
+ }
10591
+ };
10229
10592
  }
10230
10593
 
10231
10594
  // src/utils/auth-routes.ts
@@ -10462,7 +10825,7 @@ function requireEnv(names, env) {
10462
10825
  "requireEnv() requires at least one environment variable name."
10463
10826
  );
10464
10827
  }
10465
- const source = env ?? readProcessEnv3();
10828
+ const source = env ?? readProcessEnv4();
10466
10829
  for (const name of names) {
10467
10830
  const value = source[name]?.trim();
10468
10831
  if (value) {
@@ -10477,7 +10840,7 @@ function readEnv(names, env) {
10477
10840
  if (!names.length) {
10478
10841
  return void 0;
10479
10842
  }
10480
- const source = env ?? readProcessEnv3();
10843
+ const source = env ?? readProcessEnv4();
10481
10844
  for (const name of names) {
10482
10845
  const value = source[name]?.trim();
10483
10846
  if (value) {
@@ -10486,7 +10849,7 @@ function readEnv(names, env) {
10486
10849
  }
10487
10850
  return void 0;
10488
10851
  }
10489
- function readProcessEnv3() {
10852
+ function readProcessEnv4() {
10490
10853
  try {
10491
10854
  const processEnv = globalThis.process?.env;
10492
10855
  return processEnv ?? {};
@@ -10513,79 +10876,469 @@ function proxyRequestHeaders(request2) {
10513
10876
  return headers;
10514
10877
  }
10515
10878
 
10516
- // src/organization/ensure-active-organization.ts
10517
- function normalizeOrganizationId(value) {
10518
- if (typeof value !== "string") {
10519
- return null;
10879
+ // src/tables/catalog.ts
10880
+ var POSTGRES_CATALOG_SQL = {
10881
+ columns: `
10882
+ SELECT
10883
+ n.nspname AS schema_name,
10884
+ c.relname AS table_name,
10885
+ a.attname AS column_name,
10886
+ format_type(a.atttypid, a.atttypmod) AS data_type,
10887
+ NOT a.attnotnull AS is_nullable
10888
+ FROM pg_attribute a
10889
+ JOIN pg_class c ON c.oid = a.attrelid
10890
+ JOIN pg_namespace n ON n.oid = c.relnamespace
10891
+ WHERE c.relkind IN ('r', 'p')
10892
+ AND a.attnum > 0
10893
+ AND NOT a.attisdropped
10894
+ AND n.nspname = ANY($1::text[])
10895
+ ORDER BY n.nspname, c.relname, a.attnum;
10896
+ `,
10897
+ foreignKeys: `
10898
+ SELECT
10899
+ sn.nspname AS source_schema,
10900
+ sc.relname AS source_table,
10901
+ con.conname AS constraint_name,
10902
+ ARRAY_AGG(sa.attname ORDER BY cols.ordinality) AS source_columns,
10903
+ tn.nspname AS target_schema,
10904
+ tc.relname AS target_table,
10905
+ ARRAY_AGG(ta.attname ORDER BY cols.ordinality) AS target_columns,
10906
+ EXISTS (
10907
+ SELECT 1
10908
+ FROM pg_constraint uq
10909
+ WHERE uq.conrelid = con.conrelid
10910
+ AND uq.contype IN ('p', 'u')
10911
+ AND uq.conkey = con.conkey
10912
+ ) AS source_is_unique
10913
+ FROM pg_constraint con
10914
+ JOIN pg_class sc ON sc.oid = con.conrelid
10915
+ JOIN pg_namespace sn ON sn.oid = sc.relnamespace
10916
+ JOIN pg_class tc ON tc.oid = con.confrelid
10917
+ JOIN pg_namespace tn ON tn.oid = tc.relnamespace
10918
+ JOIN unnest(con.conkey, con.confkey) WITH ORDINALITY AS cols(source_attnum, target_attnum, ordinality) ON TRUE
10919
+ JOIN pg_attribute sa ON sa.attrelid = con.conrelid AND sa.attnum = cols.source_attnum
10920
+ JOIN pg_attribute ta ON ta.attrelid = con.confrelid AND ta.attnum = cols.target_attnum
10921
+ WHERE con.contype = 'f'
10922
+ AND sn.nspname = ANY($1::text[])
10923
+ AND tn.nspname = ANY($1::text[])
10924
+ GROUP BY
10925
+ sn.nspname,
10926
+ sc.relname,
10927
+ con.conname,
10928
+ tn.nspname,
10929
+ tc.relname,
10930
+ con.conkey,
10931
+ con.conrelid
10932
+ ORDER BY sn.nspname, sc.relname, con.conname;
10933
+ `,
10934
+ primaryKeys: `
10935
+ SELECT
10936
+ n.nspname AS schema_name,
10937
+ c.relname AS table_name,
10938
+ ARRAY_AGG(a.attname ORDER BY ck.ordinality) AS columns
10939
+ FROM pg_constraint con
10940
+ JOIN pg_class c ON c.oid = con.conrelid
10941
+ JOIN pg_namespace n ON n.oid = c.relnamespace
10942
+ JOIN unnest(con.conkey) WITH ORDINALITY AS ck(attnum, ordinality) ON TRUE
10943
+ JOIN pg_attribute a ON a.attrelid = c.oid AND a.attnum = ck.attnum
10944
+ WHERE con.contype = 'p'
10945
+ AND n.nspname = ANY($1::text[])
10946
+ GROUP BY n.nspname, c.relname
10947
+ ORDER BY n.nspname, c.relname;
10948
+ `
10949
+ };
10950
+ function parseAthenaTableSchemaScope(value) {
10951
+ return value.split(",").map((entry) => entry.trim()).filter(
10952
+ (entry, index, values) => entry.length > 0 && values.indexOf(entry) === index
10953
+ );
10954
+ }
10955
+ function escapeSqlLiteral(value) {
10956
+ return value.replace(/'/g, "''");
10957
+ }
10958
+ function buildSchemaArrayLiteral(schemas) {
10959
+ const literals = schemas.map((schema) => `'${escapeSqlLiteral(schema)}'`).join(", ");
10960
+ return `ARRAY[${literals}]`;
10961
+ }
10962
+ function inlineSchemaLiteral(sql, schemas) {
10963
+ return sql.replace(
10964
+ /\$1::text\[\]/g,
10965
+ `${buildSchemaArrayLiteral(schemas)}::text[]`
10966
+ );
10967
+ }
10968
+ function buildAthenaTableCatalogQueries(schemas) {
10969
+ return {
10970
+ columns: inlineSchemaLiteral(POSTGRES_CATALOG_SQL.columns, schemas),
10971
+ foreignKeys: inlineSchemaLiteral(POSTGRES_CATALOG_SQL.foreignKeys, schemas),
10972
+ primaryKeys: inlineSchemaLiteral(POSTGRES_CATALOG_SQL.primaryKeys, schemas)
10973
+ };
10974
+ }
10975
+ function tableKey(schema, table) {
10976
+ return `${schema}.${table}`;
10977
+ }
10978
+ function relationKey(...parts) {
10979
+ const base = parts.join("_").replace(/[^A-Za-z0-9_]+/g, "_").replace(/^_+|_+$/g, "");
10980
+ return base.length > 0 ? base : "relation";
10981
+ }
10982
+ function parsePostgresArrayLiteral(text) {
10983
+ const body = text.slice(1, -1).trim();
10984
+ if (!body) {
10985
+ return [];
10520
10986
  }
10521
- const normalized = value.trim();
10522
- return normalized.length > 0 ? normalized : null;
10987
+ const values = [];
10988
+ let current = "";
10989
+ let inQuotes = false;
10990
+ let escaped = false;
10991
+ for (const char of body) {
10992
+ if (escaped) {
10993
+ current += char;
10994
+ escaped = false;
10995
+ continue;
10996
+ }
10997
+ if (char === "\\") {
10998
+ escaped = true;
10999
+ continue;
11000
+ }
11001
+ if (char === '"') {
11002
+ inQuotes = !inQuotes;
11003
+ continue;
11004
+ }
11005
+ if (char === "," && !inQuotes) {
11006
+ values.push(current);
11007
+ current = "";
11008
+ continue;
11009
+ }
11010
+ current += char;
11011
+ }
11012
+ values.push(current);
11013
+ return values.map((value) => value.trim()).filter((value) => value.length > 0);
10523
11014
  }
10524
- function defaultSelectOrganizationId(organizations) {
10525
- for (const organization of organizations) {
10526
- const id = normalizeOrganizationId(organization.id);
10527
- if (id) {
10528
- return id;
11015
+ function coerceStringArray(value) {
11016
+ if (value == null) {
11017
+ return [];
11018
+ }
11019
+ if (Array.isArray(value)) {
11020
+ return value.map((entry) => entry.trim()).filter(Boolean);
11021
+ }
11022
+ if (typeof value !== "string") {
11023
+ return [];
11024
+ }
11025
+ const trimmedValue = value.trim();
11026
+ if (!trimmedValue) {
11027
+ return [];
11028
+ }
11029
+ if (trimmedValue.startsWith("{") && trimmedValue.endsWith("}")) {
11030
+ return parsePostgresArrayLiteral(trimmedValue);
11031
+ }
11032
+ return trimmedValue.split(",").map((entry) => entry.trim()).filter(Boolean);
11033
+ }
11034
+ function createTableCatalog() {
11035
+ const tables = /* @__PURE__ */ new Map();
11036
+ const ensureTable = (schema, name) => {
11037
+ const id = tableKey(schema, name);
11038
+ const existingTable = tables.get(id);
11039
+ if (existingTable) {
11040
+ return existingTable;
11041
+ }
11042
+ const nextTable = {
11043
+ columns: [],
11044
+ id,
11045
+ name,
11046
+ primaryKey: [],
11047
+ relationMap: /* @__PURE__ */ new Map(),
11048
+ schema
11049
+ };
11050
+ tables.set(id, nextTable);
11051
+ return nextTable;
11052
+ };
11053
+ const upsertRelation = (table, key, relation) => {
11054
+ table.relationMap.set(key, relation);
11055
+ };
11056
+ return {
11057
+ addColumnRows(columnRows) {
11058
+ for (const row of columnRows) {
11059
+ const table = ensureTable(row.schema_name, row.table_name);
11060
+ table.columns.push({
11061
+ dataType: row.data_type,
11062
+ isNullable: row.is_nullable,
11063
+ isPrimaryKey: false,
11064
+ name: row.column_name
11065
+ });
11066
+ }
11067
+ },
11068
+ addForeignKeyRows(foreignKeyRows) {
11069
+ for (const row of foreignKeyRows) {
11070
+ const sourceTable = ensureTable(row.source_schema, row.source_table);
11071
+ const targetTable = ensureTable(row.target_schema, row.target_table);
11072
+ upsertRelation(
11073
+ sourceTable,
11074
+ relationKey(row.constraint_name, row.target_table),
11075
+ {
11076
+ name: row.constraint_name,
11077
+ targetSchema: row.target_schema,
11078
+ targetTable: row.target_table
11079
+ }
11080
+ );
11081
+ upsertRelation(targetTable, relationKey(row.source_table), {
11082
+ name: relationKey(row.source_table, row.constraint_name),
11083
+ targetSchema: row.source_schema,
11084
+ targetTable: row.source_table
11085
+ });
11086
+ }
11087
+ },
11088
+ addManyToManyRows(foreignKeyRows) {
11089
+ const foreignKeysBySourceTable = /* @__PURE__ */ new Map();
11090
+ for (const foreignKey of foreignKeyRows) {
11091
+ const key = tableKey(foreignKey.source_schema, foreignKey.source_table);
11092
+ const current = foreignKeysBySourceTable.get(key) ?? {
11093
+ foreignKeys: [],
11094
+ schema: foreignKey.source_schema,
11095
+ table: foreignKey.source_table
11096
+ };
11097
+ current.foreignKeys.push(foreignKey);
11098
+ foreignKeysBySourceTable.set(key, current);
11099
+ }
11100
+ for (const candidate of foreignKeysBySourceTable.values()) {
11101
+ const bridgeTable = tables.get(
11102
+ tableKey(candidate.schema, candidate.table)
11103
+ );
11104
+ if (!bridgeTable || candidate.foreignKeys.length !== 2) {
11105
+ continue;
11106
+ }
11107
+ const combinedForeignColumns = Array.from(
11108
+ new Set(
11109
+ candidate.foreignKeys.flatMap(
11110
+ (foreignKey) => coerceStringArray(foreignKey.source_columns)
11111
+ )
11112
+ )
11113
+ );
11114
+ if (bridgeTable.primaryKey.length === 0 || combinedForeignColumns.length !== bridgeTable.primaryKey.length || !bridgeTable.primaryKey.every(
11115
+ (column) => combinedForeignColumns.includes(column)
11116
+ )) {
11117
+ continue;
11118
+ }
11119
+ const [firstForeignKey, secondForeignKey] = candidate.foreignKeys;
11120
+ const firstTarget = tables.get(
11121
+ tableKey(firstForeignKey.target_schema, firstForeignKey.target_table)
11122
+ );
11123
+ const secondTarget = tables.get(
11124
+ tableKey(
11125
+ secondForeignKey.target_schema,
11126
+ secondForeignKey.target_table
11127
+ )
11128
+ );
11129
+ if (!(firstTarget && secondTarget)) {
11130
+ continue;
11131
+ }
11132
+ upsertRelation(
11133
+ firstTarget,
11134
+ relationKey(candidate.table, secondForeignKey.target_table),
11135
+ {
11136
+ name: relationKey(
11137
+ candidate.table,
11138
+ secondForeignKey.constraint_name
11139
+ ),
11140
+ targetSchema: secondForeignKey.target_schema,
11141
+ targetTable: secondForeignKey.target_table
11142
+ }
11143
+ );
11144
+ upsertRelation(
11145
+ secondTarget,
11146
+ relationKey(candidate.table, firstForeignKey.target_table),
11147
+ {
11148
+ name: relationKey(candidate.table, firstForeignKey.constraint_name),
11149
+ targetSchema: firstForeignKey.target_schema,
11150
+ targetTable: firstForeignKey.target_table
11151
+ }
11152
+ );
11153
+ }
11154
+ },
11155
+ addPrimaryKeyRows(primaryKeyRows) {
11156
+ for (const row of primaryKeyRows) {
11157
+ const table = ensureTable(row.schema_name, row.table_name);
11158
+ const primaryKey = coerceStringArray(row.columns);
11159
+ table.primaryKey = primaryKey;
11160
+ for (const columnName of primaryKey) {
11161
+ const column = table.columns.find(
11162
+ (candidate) => candidate.name === columnName
11163
+ );
11164
+ if (column) {
11165
+ column.isPrimaryKey = true;
11166
+ }
11167
+ }
11168
+ }
11169
+ },
11170
+ toResponse(database) {
11171
+ return {
11172
+ database,
11173
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
11174
+ tables: [...tables.values()].map((table) => ({
11175
+ columns: [...table.columns].sort(
11176
+ (left, right) => left.name.localeCompare(right.name)
11177
+ ),
11178
+ id: table.id,
11179
+ name: table.name,
11180
+ primaryKey: [...table.primaryKey],
11181
+ relations: [...table.relationMap.values()].map((relation) => ({
11182
+ columns: tables.get(
11183
+ tableKey(relation.targetSchema, relation.targetTable)
11184
+ )?.columns ?? [],
11185
+ name: relation.name,
11186
+ targetSchema: relation.targetSchema,
11187
+ targetTable: relation.targetTable
11188
+ })).sort(
11189
+ (left, right) => left.name.localeCompare(right.name)
11190
+ ),
11191
+ schema: table.schema
11192
+ })).sort(
11193
+ (left, right) => left.id.localeCompare(right.id)
11194
+ )
11195
+ };
10529
11196
  }
11197
+ };
11198
+ }
11199
+ async function queryRows(client, query) {
11200
+ const result = await client.query(query);
11201
+ if (result.error || result.status < 200 || result.status >= 300) {
11202
+ const errorMessage = typeof result.error === "string" ? result.error : result.error && typeof result.error === "object" && "message" in result.error && typeof result.error.message === "string" ? result.error.message : `Athena gateway query failed with status ${result.status}.`;
11203
+ throw new Error(errorMessage);
10530
11204
  }
10531
- return null;
11205
+ return Array.isArray(result.data) ? result.data : [];
10532
11206
  }
10533
- async function ensureActiveOrganization(options) {
10534
- const currentActiveOrganizationId = normalizeOrganizationId(
10535
- options.session?.session?.activeOrganizationId
10536
- );
10537
- if (currentActiveOrganizationId) {
11207
+ function isAthenaTableSchemaConfig(value) {
11208
+ if (typeof value !== "object" || value === null) {
11209
+ return false;
11210
+ }
11211
+ const config = value;
11212
+ return typeof config.gatewayUrl === "string" && typeof config.gatewayKey === "string" && typeof config.gatewayDatabase === "string" && typeof config.schemaScope === "string" && typeof config.clientName === "string";
11213
+ }
11214
+ function hasAthenaTableSchemaCredentials(config) {
11215
+ return config.gatewayUrl.trim().length > 0 && config.gatewayKey.trim().length > 0 && config.gatewayDatabase.trim().length > 0;
11216
+ }
11217
+ async function fetchAthenaTableCatalog(config, options = {}) {
11218
+ const schemas = parseAthenaTableSchemaScope(config.schemaScope);
11219
+ if (schemas.length === 0) {
10538
11220
  return {
10539
- activeOrganizationId: currentActiveOrganizationId,
10540
- didSetActiveOrganization: false
11221
+ database: config.gatewayDatabase,
11222
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
11223
+ tables: []
10541
11224
  };
10542
11225
  }
10543
- let organizations;
11226
+ const queries = buildAthenaTableCatalogQueries(schemas);
11227
+ const client = options.client ?? createClient({
11228
+ url: config.gatewayUrl.trim(),
11229
+ key: config.gatewayKey.trim(),
11230
+ client: config.clientName.trim() || void 0
11231
+ });
11232
+ const [columnRows, primaryKeyRows, foreignKeyRows] = await Promise.all([
11233
+ queryRows(client, queries.columns),
11234
+ queryRows(client, queries.primaryKeys),
11235
+ queryRows(client, queries.foreignKeys)
11236
+ ]);
11237
+ const catalog = createTableCatalog();
11238
+ catalog.addColumnRows(columnRows);
11239
+ catalog.addPrimaryKeyRows(primaryKeyRows);
11240
+ catalog.addForeignKeyRows(foreignKeyRows);
11241
+ catalog.addManyToManyRows(foreignKeyRows);
11242
+ return catalog.toResponse(config.gatewayDatabase);
11243
+ }
11244
+ var fetchTableCatalog = fetchAthenaTableCatalog;
11245
+
11246
+ // src/tables/schema-handlers.ts
11247
+ var ATHENA_TABLE_SCHEMA_ROUTE = "/api/tables/schema";
11248
+ function json2(body, init) {
11249
+ const headers = new Headers(init?.headers);
11250
+ if (!headers.has("content-type")) {
11251
+ headers.set("content-type", "application/json; charset=utf-8");
11252
+ }
11253
+ return new Response(JSON.stringify(body), {
11254
+ status: init?.status ?? 200,
11255
+ headers
11256
+ });
11257
+ }
11258
+ async function handleAthenaTableSchemaPost(request2, options) {
11259
+ const payload = await request2.json().catch(() => null);
11260
+ let config = isAthenaTableSchemaConfig(
11261
+ payload?.config
11262
+ ) ? payload.config : null;
11263
+ if (config && options?.resolveConfig) {
11264
+ config = await options.resolveConfig(config, request2);
11265
+ }
11266
+ if (!config || !isAthenaTableSchemaConfig(config)) {
11267
+ return json2(
11268
+ {
11269
+ error: "The Athena tables showcase config is invalid."
11270
+ },
11271
+ { status: 400 }
11272
+ );
11273
+ }
11274
+ if (!hasAthenaTableSchemaCredentials(config)) {
11275
+ return json2(
11276
+ {
11277
+ error: "Gateway URL, API key, and database are required for schema introspection."
11278
+ },
11279
+ { status: 400 }
11280
+ );
11281
+ }
10544
11282
  try {
10545
- organizations = await options.listOrganizations();
11283
+ const response = await fetchAthenaTableCatalog(
11284
+ config,
11285
+ {
11286
+ client: options?.client
11287
+ }
11288
+ );
11289
+ return json2(response);
10546
11290
  } catch (error) {
10547
- options.onError?.(error);
10548
- return {
10549
- activeOrganizationId: null,
10550
- didSetActiveOrganization: false
10551
- };
11291
+ return json2(
11292
+ {
11293
+ error: error instanceof Error ? error.message : "Athena schema introspection failed."
11294
+ },
11295
+ { status: 500 }
11296
+ );
10552
11297
  }
10553
- if (organizations.length === 0) {
10554
- return {
10555
- activeOrganizationId: null,
10556
- didSetActiveOrganization: false
10557
- };
11298
+ }
11299
+ function createAthenaTableSchemaHandlers(options) {
11300
+ return {
11301
+ POST: (request2) => handleAthenaTableSchemaPost(request2, options)
11302
+ };
11303
+ }
11304
+
11305
+ // src/next/server.ts
11306
+ function warnEmptyServerScope() {
11307
+ if (typeof process !== "undefined" && process.env?.NODE_ENV === "production") {
11308
+ return;
10558
11309
  }
10559
- const selectedOrganizationId = normalizeOrganizationId(
10560
- (options.selectOrganizationId ?? defaultSelectOrganizationId)(organizations)
11310
+ console.warn(
11311
+ "[athena] createAthenaServerClient/resolveAthenaServerContext: `scope` was provided without userId or organizationId. Gateway identity headers will not be set from scope. Pass at least one field, or omit scope."
10561
11312
  );
10562
- if (!selectedOrganizationId) {
11313
+ }
11314
+ function resolveServerIdentity(options) {
11315
+ const session = options.session ?? null;
11316
+ const sessionUserId = session?.user?.id ?? null;
11317
+ const sessionOrganizationId = session?.session?.activeOrganizationId ?? null;
11318
+ const scope = options.scope;
11319
+ if (scope === void 0) {
10563
11320
  return {
10564
- activeOrganizationId: null,
10565
- didSetActiveOrganization: false
11321
+ userId: sessionUserId,
11322
+ organizationId: sessionOrganizationId
10566
11323
  };
10567
11324
  }
10568
- try {
10569
- await options.setActiveOrganization(selectedOrganizationId);
10570
- return {
10571
- activeOrganizationId: selectedOrganizationId,
10572
- didSetActiveOrganization: true
10573
- };
10574
- } catch (error) {
10575
- options.onError?.(error);
10576
- return {
10577
- activeOrganizationId: null,
10578
- didSetActiveOrganization: false
10579
- };
11325
+ const scopeHasUserId = Object.hasOwn(scope, "userId");
11326
+ const scopeHasOrganizationId = Object.hasOwn(scope, "organizationId");
11327
+ if (!scopeHasUserId && !scopeHasOrganizationId) {
11328
+ warnEmptyServerScope();
10580
11329
  }
11330
+ return {
11331
+ userId: scopeHasUserId ? scope.userId ?? null : sessionUserId,
11332
+ organizationId: scopeHasOrganizationId ? scope.organizationId ?? null : sessionOrganizationId
11333
+ };
10581
11334
  }
10582
-
10583
- // src/next/server.ts
10584
11335
  async function resolveAthenaServerContext(options = {}) {
10585
11336
  const request2 = await resolveNextRequestContext(options);
10586
11337
  const session = options.session ?? null;
10587
- const userId = session?.user?.id ?? null;
10588
- const organizationId = session?.session?.activeOrganizationId ?? null;
11338
+ const { userId, organizationId } = resolveServerIdentity({
11339
+ session,
11340
+ scope: options.scope
11341
+ });
10589
11342
  return {
10590
11343
  request: {
10591
11344
  ...request2,
@@ -10603,6 +11356,7 @@ async function createAthenaServerClient(options) {
10603
11356
  requestCookies,
10604
11357
  forceNoCache,
10605
11358
  session,
11359
+ scope,
10606
11360
  headers: requestScopedHeaders,
10607
11361
  ...clientConfig
10608
11362
  } = options;
@@ -10611,7 +11365,8 @@ async function createAthenaServerClient(options) {
10611
11365
  requestCookies,
10612
11366
  forceNoCache,
10613
11367
  headers: requestScopedHeaders,
10614
- session
11368
+ session,
11369
+ scope
10615
11370
  });
10616
11371
  const configuredContext = clientConfig.context;
10617
11372
  return createClient({
@@ -10623,6 +11378,6 @@ async function createAthenaServerClient(options) {
10623
11378
  });
10624
11379
  }
10625
11380
 
10626
- 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_SESSION_BRIDGE_ROUTE, ATHENA_AUTH_SESSION_COOKIE_NAME, ATHENA_AUTH_SESSION_COOKIE_NAMES, 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, DISABLE_COOKIE_CACHE_QUERY_PARAM, DISABLE_COOKIE_CACHE_QUERY_VALUE, LOCAL_DEV_ORIGIN, SESSION_COOKIE_PATTERNS, SESSION_DATA_HEADER, applyAthenaApiKeyHeaders, applyAthenaAuthContextHeaders, applyAthenaPgUriHeaders, asNonEmptyString, asString, buildAthenaGatewayHeaders, buildAthenaRequestHeaders, buildServiceRequestHeaders, clearAthenaAuthSessionOnAppHost, clearAuthCookies, createAthenaAuthSessionBridgeHandlers, createAthenaAuthSessionBridgePathHandlers, createAthenaServerClient, createAuthModeRedirects, createAuthRoutes, createFreshSessionLookupUrl, ensureActiveOrganization, getOriginFromHeaders, handleAthenaAuthSessionBridgeDelete, handleAthenaAuthSessionBridgePost, hasAuthSessionCookie, hasHeaderIgnoreCase, isAbsoluteUrl, isAthenaAuthSessionBridgePath, isAuthMode, isDynamicServerUsageError, normalizeAthenaAuthBaseUrl, persistAthenaAuthSessionOnAppHost, proxyRequestHeaders, readAthenaAuthUpstreamUrlFromEnv, readEnv, readTrimmedString, requireEnv, resolveAthenaAuthClientBaseUrl, resolveAthenaAuthRequestUrl, resolveAthenaAuthUpstreamUrl, resolveAthenaServerContext, resolveAuthModeRedirect, resolveAuthViewFromSegment, resolveEmailVerificationCallbackUrl, resolveHeaderValue, resolveNextRequestContext, resolveRequestHeaderOverrides, resolveSessionBridgePayload, shouldRedirectAuthenticatedAuthMode, shouldRedirectAuthenticatedAuthView };
11381
+ 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_SESSION_BRIDGE_ROUTE, ATHENA_AUTH_SESSION_COOKIE_NAME, ATHENA_AUTH_SESSION_COOKIE_NAMES, ATHENA_AUTH_UPSTREAM_ENV_KEYS, ATHENA_AUTH_UPSTREAM_URL_ENV_NAMES, ATHENA_AUTH_VERIFY_EMAIL_PATH, ATHENA_SESSION_DATA_HEADER, ATHENA_TABLE_SCHEMA_ROUTE, 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, DISABLE_COOKIE_CACHE_QUERY_PARAM, DISABLE_COOKIE_CACHE_QUERY_VALUE, LOCAL_DEV_ORIGIN, SESSION_COOKIE_PATTERNS, SESSION_DATA_HEADER, applyAthenaApiKeyHeaders, applyAthenaAuthContextHeaders, applyAthenaPgUriHeaders, asNonEmptyString, asString, buildAthenaGatewayHeaders, buildAthenaRequestHeaders, buildAthenaTableCatalogQueries, buildServiceRequestHeaders, clearAthenaAuthSessionOnAppHost, clearAuthCookies, createAthenaAuthSessionBridgeHandlers, createAthenaAuthSessionBridgePathHandlers, createAthenaServerClient, createAthenaTableSchemaHandlers, createAuthModeRedirects, createAuthRoutes, createFreshSessionLookupUrl, ensureActiveOrganization, fetchAthenaTableCatalog, fetchTableCatalog, getOriginFromHeaders, getServerSession, handleAthenaAuthSessionBridgeDelete, handleAthenaAuthSessionBridgePost, handleAthenaTableSchemaPost, hasAthenaTableSchemaCredentials, hasAuthSessionCookie, hasHeaderIgnoreCase, isAbsoluteUrl, isAthenaAuthSessionBridgePath, isAthenaTableSchemaConfig, isAuthMode, isDynamicServerUsageError, normalizeAthenaAuthBaseUrl, parseAthenaSessionDataHeader, parseAthenaTableSchemaScope, persistAthenaAuthSessionOnAppHost, proxyRequestHeaders, readAthenaAuthUpstreamUrlFromEnv, readEnv, readTrimmedString, requireEnv, resolveAthenaAuthClientBaseUrl, resolveAthenaAuthRequestUrl, resolveAthenaAuthUpstreamUrl, resolveAthenaServerContext, resolveAuthModeRedirect, resolveAuthViewFromSegment, resolveEmailVerificationCallbackUrl, resolveHeaderValue, resolveNextRequestContext, resolveRequestHeaderOverrides, resolveSessionBridgePayload, shouldRedirectAuthenticatedAuthMode, shouldRedirectAuthenticatedAuthView };
10627
11382
  //# sourceMappingURL=server.js.map
10628
11383
  //# sourceMappingURL=server.js.map