@xylex-group/athena 2.3.0 → 2.4.1

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 (42) hide show
  1. package/README.md +195 -106
  2. package/dist/browser.cjs +870 -154
  3. package/dist/browser.cjs.map +1 -1
  4. package/dist/browser.d.cts +7 -7
  5. package/dist/browser.d.ts +7 -7
  6. package/dist/browser.js +869 -155
  7. package/dist/browser.js.map +1 -1
  8. package/dist/cli/index.cjs +905 -144
  9. package/dist/cli/index.cjs.map +1 -1
  10. package/dist/cli/index.d.cts +3 -3
  11. package/dist/cli/index.d.ts +3 -3
  12. package/dist/cli/index.js +905 -144
  13. package/dist/cli/index.js.map +1 -1
  14. package/dist/index.cjs +870 -154
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +7 -7
  17. package/dist/index.d.ts +7 -7
  18. package/dist/index.js +869 -155
  19. package/dist/index.js.map +1 -1
  20. package/dist/{model-form-hoE2jHIi.d.cts → model-form-4LPnOPAF.d.cts} +9 -5
  21. package/dist/{model-form-BpDXlbxb.d.ts → model-form-CO4-LmNC.d.ts} +9 -5
  22. package/dist/{pipeline-BNIw8pDQ.d.ts → pipeline-CR4V15jF.d.ts} +1 -1
  23. package/dist/{pipeline-DNIpEsN8.d.cts → pipeline-DZeExYMA.d.cts} +1 -1
  24. package/dist/{react-email-qPA1wjFV.d.ts → react-email-6mOyxBo4.d.cts} +60 -13
  25. package/dist/{react-email-BvyCZnfW.d.cts → react-email-Buhcpglm.d.ts} +60 -13
  26. package/dist/react.cjs +333 -16
  27. package/dist/react.cjs.map +1 -1
  28. package/dist/react.d.cts +4 -4
  29. package/dist/react.d.ts +4 -4
  30. package/dist/react.js +333 -16
  31. package/dist/react.js.map +1 -1
  32. package/dist/{types-A5e97acl.d.cts → types-09Q4D86N.d.cts} +23 -2
  33. package/dist/{types-A5e97acl.d.ts → types-09Q4D86N.d.ts} +23 -2
  34. package/dist/{types-bDlr4u7p.d.cts → types-D1JvL21V.d.cts} +1 -1
  35. package/dist/{types-BnD22-vb.d.ts → types-DU3gNdFv.d.ts} +1 -1
  36. package/dist/utils.cjs +131 -0
  37. package/dist/utils.cjs.map +1 -1
  38. package/dist/utils.d.cts +42 -1
  39. package/dist/utils.d.ts +42 -1
  40. package/dist/utils.js +117 -1
  41. package/dist/utils.js.map +1 -1
  42. package/package.json +40 -40
package/dist/cli/index.js CHANGED
@@ -497,6 +497,7 @@ function classifyKind(status, code, message) {
497
497
  if (status === 404 || hasNotFoundPattern) return "not_found";
498
498
  if (status === 401 || status === 403 || hasAuthPattern) return "auth";
499
499
  if (status === 429 || hasRateLimitPattern) return "rate_limit";
500
+ if (code === "INVALID_URL") return "validation";
500
501
  if (status === 400 || status === 422 || hasValidationPattern) return "validation";
501
502
  if (code === "NETWORK_ERROR" || status === 0 || status !== void 0 && status >= 500 || hasTransientPattern) {
502
503
  return "transient";
@@ -504,6 +505,9 @@ function classifyKind(status, code, message) {
504
505
  return "unknown";
505
506
  }
506
507
  function toAthenaErrorCode(kind, status, gatewayCode) {
508
+ if (gatewayCode === "INVALID_URL") {
509
+ return AthenaErrorCode.ValidationFailed;
510
+ }
507
511
  if (gatewayCode === "NETWORK_ERROR" || kind === "transient" && status === 0) {
508
512
  return AthenaErrorCode.NetworkUnavailable;
509
513
  }
@@ -657,6 +661,54 @@ function normalizeAthenaError(resultOrError, context) {
657
661
  raw: resultOrError
658
662
  };
659
663
  }
664
+ function defaultShouldRetry(error) {
665
+ const normalized = normalizeAthenaError(error);
666
+ return normalized.kind === "transient" || normalized.kind === "rate_limit";
667
+ }
668
+ function computeDelayMs(attempt, error, config) {
669
+ const baseDelay = config.baseDelayMs;
670
+ const rawDelay = typeof config.backoff === "function" ? config.backoff(attempt, error) : config.backoff === "linear" ? baseDelay * attempt : baseDelay * Math.pow(2, attempt - 1);
671
+ const safeDelay = Number.isFinite(rawDelay) ? Math.max(0, rawDelay) : 0;
672
+ const clamped = Math.min(config.maxDelayMs, safeDelay);
673
+ const jitterFactor = typeof config.jitter === "number" ? Math.max(0, Math.min(1, config.jitter)) : config.jitter ? 0.2 : 0;
674
+ if (!jitterFactor) return clamped;
675
+ const deviation = clamped * jitterFactor;
676
+ const offset = (Math.random() * 2 - 1) * deviation;
677
+ return Math.max(0, clamped + offset);
678
+ }
679
+ function sleep(ms) {
680
+ if (ms <= 0) return Promise.resolve();
681
+ return new Promise((resolve3) => {
682
+ setTimeout(resolve3, ms);
683
+ });
684
+ }
685
+ async function withRetry(config, fn) {
686
+ const retries = Math.max(0, Math.trunc(config.retries));
687
+ const shouldRetry = config.shouldRetry ?? defaultShouldRetry;
688
+ const resolvedConfig = {
689
+ baseDelayMs: config.baseDelayMs ?? 100,
690
+ maxDelayMs: config.maxDelayMs ?? 1e4,
691
+ backoff: config.backoff ?? "exponential",
692
+ jitter: config.jitter ?? false
693
+ };
694
+ for (let attempts = 0; attempts <= retries; attempts += 1) {
695
+ try {
696
+ return await fn();
697
+ } catch (error) {
698
+ if (attempts >= retries) {
699
+ throw error;
700
+ }
701
+ const currentAttempt = attempts + 1;
702
+ const retry = await shouldRetry(error, currentAttempt);
703
+ if (!retry) {
704
+ throw error;
705
+ }
706
+ const delay = computeDelayMs(currentAttempt, error, resolvedConfig);
707
+ await sleep(delay);
708
+ }
709
+ }
710
+ throw new Error("withRetry reached an unexpected state");
711
+ }
660
712
 
661
713
  // src/generator/schema-selection.ts
662
714
  var DEFAULT_POSTGRES_SCHEMAS = ["public"];
@@ -1357,13 +1409,114 @@ function generateArtifactsFromSnapshot(snapshot, config) {
1357
1409
  return new ArtifactComposer(snapshot, normalizedConfig).compose();
1358
1410
  }
1359
1411
 
1412
+ // src/gateway/url.ts
1413
+ var ATHENA_DEFAULT_BASE_URL = "https://athena-db.com";
1414
+ function describeReceivedValue(value) {
1415
+ if (value === void 0) return "undefined";
1416
+ if (value === null) return "null";
1417
+ if (typeof value === "string") {
1418
+ return value.trim().length > 0 ? JSON.stringify(value) : "an empty string";
1419
+ }
1420
+ return `${typeof value} ${JSON.stringify(value)}`;
1421
+ }
1422
+ function invalidBaseUrlError(message, hint) {
1423
+ return new AthenaGatewayError({
1424
+ code: "INVALID_URL",
1425
+ message,
1426
+ status: 0,
1427
+ hint
1428
+ });
1429
+ }
1430
+ function normalizeAthenaGatewayBaseUrl(input, options = {}) {
1431
+ const label = options.label ?? "Athena gateway base URL";
1432
+ const candidate = input ?? options.defaultBaseUrl;
1433
+ if (candidate === void 0 || candidate === null) {
1434
+ throw invalidBaseUrlError(
1435
+ `${label} must be a non-empty absolute http(s) URL. Received ${describeReceivedValue(input)}.`,
1436
+ 'Set ATHENA_URL (or pass createClient(url, ...)) to a full URL such as "https://mirror3.athena-db.com".'
1437
+ );
1438
+ }
1439
+ const trimmed = candidate.trim();
1440
+ if (!trimmed) {
1441
+ throw invalidBaseUrlError(
1442
+ `${label} must be a non-empty absolute http(s) URL. Received ${describeReceivedValue(candidate)}.`,
1443
+ 'Set ATHENA_URL (or pass createClient(url, ...)) to a full URL such as "https://mirror3.athena-db.com".'
1444
+ );
1445
+ }
1446
+ let parsed;
1447
+ try {
1448
+ parsed = new URL(trimmed);
1449
+ } catch {
1450
+ throw invalidBaseUrlError(
1451
+ `${label} must be a valid absolute http(s) URL. Received ${describeReceivedValue(candidate)}.`,
1452
+ 'Use a full URL including the protocol, for example "https://mirror3.athena-db.com".'
1453
+ );
1454
+ }
1455
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
1456
+ throw invalidBaseUrlError(
1457
+ `${label} must use http or https. Received ${JSON.stringify(trimmed)}.`,
1458
+ 'Use an Athena gateway URL such as "https://mirror3.athena-db.com".'
1459
+ );
1460
+ }
1461
+ if (parsed.search || parsed.hash) {
1462
+ throw invalidBaseUrlError(
1463
+ `${label} must not include query parameters or hash fragments. Received ${JSON.stringify(trimmed)}.`,
1464
+ 'Pass only the base URL. Endpoint paths such as "/gateway/fetch" are appended by the SDK.'
1465
+ );
1466
+ }
1467
+ return parsed.toString().replace(/\/+$/, "");
1468
+ }
1469
+ function buildAthenaGatewayUrl(baseUrl, path) {
1470
+ if (!path.startsWith("/")) {
1471
+ throw invalidBaseUrlError(
1472
+ `Athena gateway path must start with "/". Received ${JSON.stringify(path)}.`,
1473
+ 'Use a leading slash such as "/gateway/fetch" or "/".'
1474
+ );
1475
+ }
1476
+ return `${baseUrl}${path}`;
1477
+ }
1478
+
1479
+ // src/cookies/cookie-utils.ts
1480
+ var SECURE_COOKIE_PREFIX = "__Secure-";
1481
+ function parseCookies(cookieHeader) {
1482
+ const cookies = cookieHeader.split("; ");
1483
+ const cookieMap = /* @__PURE__ */ new Map();
1484
+ cookies.forEach((cookie) => {
1485
+ const [name, value] = cookie.split(/=(.*)/s);
1486
+ cookieMap.set(name, value);
1487
+ });
1488
+ return cookieMap;
1489
+ }
1490
+ var getSessionCookie = (request, config) => {
1491
+ const cookies = (request instanceof Headers || !("headers" in request) ? request : request.headers).get("cookie");
1492
+ if (!cookies) {
1493
+ return null;
1494
+ }
1495
+ const { cookieName = "session_token", cookiePrefix = "athena-auth" } = {};
1496
+ const parsedCookie = parseCookies(cookies);
1497
+ const getCookie = (name) => parsedCookie.get(name) || parsedCookie.get(`${SECURE_COOKIE_PREFIX}${name}`);
1498
+ const sessionToken = getCookie(`${cookiePrefix}.${cookieName}`) || getCookie(`${cookiePrefix}-${cookieName}`);
1499
+ if (sessionToken) {
1500
+ return sessionToken;
1501
+ }
1502
+ return null;
1503
+ };
1504
+
1505
+ // package.json
1506
+ var package_default = {
1507
+ version: "2.4.1"
1508
+ };
1509
+
1510
+ // src/sdk-version.ts
1511
+ var PACKAGE_VERSION = package_default.version;
1512
+ function buildSdkHeaderValue(sdkName) {
1513
+ return `${sdkName} ${PACKAGE_VERSION}`;
1514
+ }
1515
+
1360
1516
  // src/gateway/client.ts
1361
- var DEFAULT_BASE_URL = "https://athena-db.com";
1362
1517
  var DEFAULT_CLIENT = "railway_direct";
1363
- var FALLBACK_SDK_VERSION = "1.3.0";
1364
1518
  var SDK_NAME = "xylex-group/athena";
1365
- var SDK_VERSION = typeof process !== "undefined" && process?.env?.npm_package_version ? process.env.npm_package_version : FALLBACK_SDK_VERSION;
1366
- var SDK_HEADER_VALUE = `${SDK_NAME} ${SDK_VERSION}`;
1519
+ var SDK_HEADER_VALUE = buildSdkHeaderValue(SDK_NAME);
1367
1520
  function parseResponseBody(rawText, contentType) {
1368
1521
  if (!rawText) {
1369
1522
  return { parsed: null, parseFailed: false };
@@ -1382,6 +1535,37 @@ function parseResponseBody(rawText, contentType) {
1382
1535
  function normalizeHeaderValue(value) {
1383
1536
  return value ? value : void 0;
1384
1537
  }
1538
+ function resolveHeaderValue(headers, candidates) {
1539
+ for (const candidate of candidates) {
1540
+ const direct = normalizeHeaderValue(headers[candidate]);
1541
+ if (direct) return direct;
1542
+ }
1543
+ const loweredCandidates = new Set(candidates.map((candidate) => candidate.toLowerCase()));
1544
+ for (const [key, value] of Object.entries(headers)) {
1545
+ if (!loweredCandidates.has(key.toLowerCase())) {
1546
+ continue;
1547
+ }
1548
+ const normalized = normalizeHeaderValue(value);
1549
+ if (normalized) return normalized;
1550
+ }
1551
+ return void 0;
1552
+ }
1553
+ function resolveBearerTokenFromAuthorizationHeader(headers) {
1554
+ const authorization = resolveHeaderValue(headers, ["Authorization"]);
1555
+ if (!authorization) {
1556
+ return void 0;
1557
+ }
1558
+ const match = authorization.match(/^Bearer\s+(.+)$/i);
1559
+ const token = match?.[1]?.trim();
1560
+ return token ? token : void 0;
1561
+ }
1562
+ function resolveSessionTokenFromCookieHeader(headers) {
1563
+ const cookie = resolveHeaderValue(headers, ["Cookie"]);
1564
+ if (!cookie) {
1565
+ return void 0;
1566
+ }
1567
+ return getSessionCookie(new Headers({ cookie })) ?? void 0;
1568
+ }
1385
1569
  function isRecord2(value) {
1386
1570
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1387
1571
  }
@@ -1499,7 +1683,7 @@ function buildRpcGetEndpoint(payload) {
1499
1683
  status: 0
1500
1684
  });
1501
1685
  }
1502
- query.set(filter.column, toRpcFilterQueryValue(filter));
1686
+ query.append(filter.column, toRpcFilterQueryValue(filter));
1503
1687
  }
1504
1688
  }
1505
1689
  const endpoint = `/rpc/${encodeURIComponent(functionName)}`;
@@ -1545,6 +1729,20 @@ function buildHeaders(config, options) {
1545
1729
  headers["apikey"] = finalApiKey;
1546
1730
  headers["x-api-key"] = headers["x-api-key"] ?? finalApiKey;
1547
1731
  }
1732
+ const explicitSessionToken = resolveHeaderValue(extraHeaders, [
1733
+ "X-Athena-Auth-Session-Token"
1734
+ ]);
1735
+ const derivedSessionToken = explicitSessionToken ?? resolveSessionTokenFromCookieHeader(extraHeaders);
1736
+ if (derivedSessionToken) {
1737
+ headers["X-Athena-Auth-Session-Token"] = derivedSessionToken;
1738
+ }
1739
+ const explicitBearerToken = resolveHeaderValue(extraHeaders, [
1740
+ "X-Athena-Auth-Bearer-Token"
1741
+ ]);
1742
+ const derivedBearerToken = explicitBearerToken ?? resolveBearerTokenFromAuthorizationHeader(extraHeaders);
1743
+ if (derivedBearerToken) {
1744
+ headers["X-Athena-Auth-Bearer-Token"] = derivedBearerToken;
1745
+ }
1548
1746
  const athenaClientKeys = ["x-athena-client", "X-Athena-Client"];
1549
1747
  Object.entries(extraHeaders).forEach(([key, value]) => {
1550
1748
  if (athenaClientKeys.includes(key)) return;
@@ -1555,9 +1753,168 @@ function buildHeaders(config, options) {
1555
1753
  });
1556
1754
  return headers;
1557
1755
  }
1756
+ function toInvalidUrlResponse(error, endpoint, method) {
1757
+ const message = error instanceof Error ? error.message : String(error);
1758
+ const gatewayError = error instanceof AthenaGatewayError ? error : new AthenaGatewayError({
1759
+ code: "INVALID_URL",
1760
+ message,
1761
+ status: 0,
1762
+ endpoint,
1763
+ method,
1764
+ cause: message,
1765
+ hint: "Set ATHENA_URL to a full http(s) URL before running queries."
1766
+ });
1767
+ return {
1768
+ ok: false,
1769
+ status: 0,
1770
+ statusText: null,
1771
+ data: null,
1772
+ error: gatewayError.message,
1773
+ errorDetails: detailsFromError(
1774
+ new AthenaGatewayError({
1775
+ code: gatewayError.code,
1776
+ message: gatewayError.message,
1777
+ status: gatewayError.status,
1778
+ endpoint,
1779
+ method,
1780
+ requestId: gatewayError.requestId,
1781
+ hint: gatewayError.hint,
1782
+ cause: gatewayError.causeDetail
1783
+ })
1784
+ ),
1785
+ raw: null
1786
+ };
1787
+ }
1788
+ function resolveGatewayBaseUrl(input) {
1789
+ return normalizeAthenaGatewayBaseUrl(input, {
1790
+ defaultBaseUrl: ATHENA_DEFAULT_BASE_URL
1791
+ });
1792
+ }
1793
+ function resolveProbePath(path) {
1794
+ if (!path) return "/";
1795
+ if (!path.startsWith("/")) {
1796
+ throw new AthenaGatewayError({
1797
+ code: "INVALID_URL",
1798
+ message: `Athena gateway probe path must start with "/". Received ${JSON.stringify(path)}.`,
1799
+ status: 0,
1800
+ hint: 'Use a leading slash such as "/" or "/health".'
1801
+ });
1802
+ }
1803
+ return path;
1804
+ }
1805
+ function mergeConnectionHeaders(baseHeaders, headers) {
1806
+ const merged = {
1807
+ ...baseHeaders,
1808
+ ...headers ?? {}
1809
+ };
1810
+ if (!merged["X-Athena-Sdk"] && !merged["x-athena-sdk"]) {
1811
+ merged["X-Athena-Sdk"] = SDK_HEADER_VALUE;
1812
+ }
1813
+ return merged;
1814
+ }
1815
+ async function performConnectionCheck(baseUrl, requestHeaders, options) {
1816
+ const path = resolveProbePath(options?.path);
1817
+ const url = buildAthenaGatewayUrl(baseUrl, path);
1818
+ try {
1819
+ const response = await fetch(url, {
1820
+ method: "GET",
1821
+ headers: mergeConnectionHeaders(requestHeaders, options?.headers),
1822
+ signal: options?.signal
1823
+ });
1824
+ const rawText = await response.text();
1825
+ const requestId = resolveRequestId(response.headers);
1826
+ const parsedBody = parseResponseBody(
1827
+ rawText ?? "",
1828
+ response.headers.get("content-type")
1829
+ );
1830
+ if (parsedBody.parseFailed) {
1831
+ const invalidJsonError = new AthenaGatewayError({
1832
+ code: "INVALID_JSON",
1833
+ message: "Gateway probe returned malformed JSON",
1834
+ status: response.status,
1835
+ method: "GET",
1836
+ requestId,
1837
+ hint: "Verify the gateway response body is valid JSON.",
1838
+ cause: rawText.slice(0, 300)
1839
+ });
1840
+ return {
1841
+ ok: false,
1842
+ reachable: true,
1843
+ status: response.status,
1844
+ statusText: resolveStatusText(response, parsedBody.parsed),
1845
+ baseUrl,
1846
+ url,
1847
+ error: invalidJsonError.message,
1848
+ errorDetails: detailsFromError(invalidJsonError),
1849
+ raw: parsedBody.parsed
1850
+ };
1851
+ }
1852
+ const parsed = parsedBody.parsed;
1853
+ if (!response.ok) {
1854
+ const httpError = new AthenaGatewayError({
1855
+ code: "HTTP_ERROR",
1856
+ message: resolveErrorMessage(
1857
+ parsed,
1858
+ `Athena gateway GET ${path} failed with status ${response.status}`
1859
+ ),
1860
+ status: response.status,
1861
+ method: "GET",
1862
+ requestId,
1863
+ hint: resolveErrorHint(parsed)
1864
+ });
1865
+ return {
1866
+ ok: false,
1867
+ reachable: true,
1868
+ status: response.status,
1869
+ statusText: resolveStatusText(response, parsed),
1870
+ baseUrl,
1871
+ url,
1872
+ error: httpError.message,
1873
+ errorDetails: detailsFromError(httpError),
1874
+ raw: parsed
1875
+ };
1876
+ }
1877
+ return {
1878
+ ok: true,
1879
+ reachable: true,
1880
+ status: response.status,
1881
+ statusText: resolveStatusText(response, parsed),
1882
+ baseUrl,
1883
+ url,
1884
+ error: void 0,
1885
+ errorDetails: null,
1886
+ raw: parsed
1887
+ };
1888
+ } catch (callError) {
1889
+ const message = callError instanceof Error ? callError.message : String(callError);
1890
+ const networkError = new AthenaGatewayError({
1891
+ code: "NETWORK_ERROR",
1892
+ message: `Network error while probing Athena gateway ${url}: ${message}`,
1893
+ method: "GET",
1894
+ cause: message,
1895
+ hint: "Check gateway URL, DNS, and network reachability."
1896
+ });
1897
+ return {
1898
+ ok: false,
1899
+ reachable: false,
1900
+ status: 0,
1901
+ statusText: null,
1902
+ baseUrl,
1903
+ url,
1904
+ error: networkError.message,
1905
+ errorDetails: detailsFromError(networkError),
1906
+ raw: null
1907
+ };
1908
+ }
1909
+ }
1558
1910
  async function callAthena(config, endpoint, method, payload, options) {
1559
- const baseUrl = (options?.baseUrl ?? config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
1560
- const url = `${baseUrl}${endpoint}`;
1911
+ let baseUrl;
1912
+ try {
1913
+ baseUrl = resolveGatewayBaseUrl(options?.baseUrl ?? config.baseUrl);
1914
+ } catch (error) {
1915
+ return toInvalidUrlResponse(error, endpoint, method);
1916
+ }
1917
+ const url = buildAthenaGatewayUrl(baseUrl, endpoint);
1561
1918
  const headers = buildHeaders(config, options);
1562
1919
  try {
1563
1920
  const requestInit = {
@@ -1654,32 +2011,44 @@ async function callAthena(config, endpoint, method, payload, options) {
1654
2011
  }
1655
2012
  }
1656
2013
  function createAthenaGatewayClient(config = {}) {
2014
+ const normalizedBaseUrl = resolveGatewayBaseUrl(config.baseUrl);
2015
+ const normalizedConfig = {
2016
+ ...config,
2017
+ baseUrl: normalizedBaseUrl
2018
+ };
1657
2019
  return {
1658
- baseUrl: (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, ""),
2020
+ baseUrl: normalizedBaseUrl,
1659
2021
  buildHeaders(options) {
1660
- return buildHeaders(config, options);
2022
+ return buildHeaders(normalizedConfig, options);
2023
+ },
2024
+ verifyConnection(options) {
2025
+ return performConnectionCheck(
2026
+ normalizedBaseUrl,
2027
+ buildHeaders(normalizedConfig),
2028
+ options
2029
+ );
1661
2030
  },
1662
2031
  fetchGateway(payload, options) {
1663
- return callAthena(config, "/gateway/fetch", "POST", payload, options);
2032
+ return callAthena(normalizedConfig, "/gateway/fetch", "POST", payload, options);
1664
2033
  },
1665
2034
  insertGateway(payload, options) {
1666
- return callAthena(config, "/gateway/insert", "PUT", payload, options);
2035
+ return callAthena(normalizedConfig, "/gateway/insert", "PUT", payload, options);
1667
2036
  },
1668
2037
  updateGateway(payload, options) {
1669
- return callAthena(config, "/gateway/update", "POST", payload, options);
2038
+ return callAthena(normalizedConfig, "/gateway/update", "POST", payload, options);
1670
2039
  },
1671
2040
  deleteGateway(payload, options) {
1672
- return callAthena(config, "/gateway/delete", "DELETE", payload, options);
2041
+ return callAthena(normalizedConfig, "/gateway/delete", "DELETE", payload, options);
1673
2042
  },
1674
2043
  rpcGateway(payload, options) {
1675
2044
  if (options?.get) {
1676
2045
  const endpoint = buildRpcGetEndpoint(payload);
1677
- return callAthena(config, endpoint, "GET", null, options);
2046
+ return callAthena(normalizedConfig, endpoint, "GET", null, options);
1678
2047
  }
1679
- return callAthena(config, "/gateway/rpc", "POST", payload, options);
2048
+ return callAthena(normalizedConfig, "/gateway/rpc", "POST", payload, options);
1680
2049
  },
1681
2050
  queryGateway(payload, options) {
1682
- return callAthena(config, "/gateway/query", "POST", payload, options);
2051
+ return callAthena(normalizedConfig, "/gateway/query", "POST", payload, options);
1683
2052
  }
1684
2053
  };
1685
2054
  }
@@ -2008,10 +2377,8 @@ async function resolveReactEmailPayloadFields(input, fields, options) {
2008
2377
 
2009
2378
  // src/auth/client.ts
2010
2379
  var DEFAULT_AUTH_BASE_URL = "http://localhost:3001/api/auth";
2011
- var FALLBACK_SDK_VERSION2 = "1.0.0";
2012
2380
  var SDK_NAME2 = "xylex-group/athena-auth";
2013
- var SDK_VERSION2 = typeof process !== "undefined" && process?.env?.npm_package_version ? process.env.npm_package_version : FALLBACK_SDK_VERSION2;
2014
- var SDK_HEADER_VALUE2 = `${SDK_NAME2} ${SDK_VERSION2}`;
2381
+ var SDK_HEADER_VALUE2 = buildSdkHeaderValue(SDK_NAME2);
2015
2382
  function normalizeBaseUrl(baseUrl) {
2016
2383
  return (baseUrl ?? DEFAULT_AUTH_BASE_URL).replace(/\/$/, "");
2017
2384
  }
@@ -3084,8 +3451,8 @@ function createAuthClient(config = {}) {
3084
3451
  // src/db/module.ts
3085
3452
  function createDbModule(input) {
3086
3453
  const db = {
3087
- from(table) {
3088
- return input.from(table);
3454
+ from(table, options) {
3455
+ return input.from(table, options);
3089
3456
  },
3090
3457
  select(table, columns, options) {
3091
3458
  return input.from(table).select(columns, options);
@@ -3190,7 +3557,19 @@ function buildGatewayCondition(operator, column, value) {
3190
3557
  function compileRelationToken(key, node) {
3191
3558
  const nested = compileSelectShape(node.select);
3192
3559
  const propertyKey = normalizeIdentifier(key, "select relation key");
3193
- const relationToken = normalizeIdentifier(node.via ?? propertyKey, "select relation token");
3560
+ if (node.schema && node.via) {
3561
+ throw new Error(
3562
+ `findMany relation "${propertyKey}" cannot combine schema and via yet; use schema with the relation key, or use via without schema`
3563
+ );
3564
+ }
3565
+ const relationTokenBase = normalizeIdentifier(node.via ?? propertyKey, "select relation token");
3566
+ if (node.schema && relationTokenBase.includes(".")) {
3567
+ throw new Error(
3568
+ `findMany relation "${propertyKey}" already resolves to a qualified relation token; do not also set schema`
3569
+ );
3570
+ }
3571
+ const relationSchema = node.schema?.trim();
3572
+ const relationToken = relationSchema ? `${normalizeIdentifier(relationSchema, "select relation schema")}.${relationTokenBase}` : relationTokenBase;
3194
3573
  const alias = node.as?.trim() || (relationToken !== propertyKey ? propertyKey : "");
3195
3574
  const prefix = alias ? `${alias}:` : "";
3196
3575
  return `${prefix}${relationToken}(${nested})`;
@@ -3219,6 +3598,23 @@ function compileSelectShape(select) {
3219
3598
  }
3220
3599
  return tokens.join(",");
3221
3600
  }
3601
+ function selectShapeUsesRelationSchema(select) {
3602
+ if (!isRecord5(select)) {
3603
+ return false;
3604
+ }
3605
+ for (const rawValue of Object.values(select)) {
3606
+ if (!isRelationSelectNode(rawValue)) {
3607
+ continue;
3608
+ }
3609
+ if (typeof rawValue.schema === "string" && rawValue.schema.trim().length > 0) {
3610
+ return true;
3611
+ }
3612
+ if (selectShapeUsesRelationSchema(rawValue.select)) {
3613
+ return true;
3614
+ }
3615
+ }
3616
+ return false;
3617
+ }
3222
3618
  function compileColumnWhere(column, input) {
3223
3619
  const normalizedColumn = normalizeIdentifier(column, "where column");
3224
3620
  if (!isRecord5(input)) {
@@ -3355,6 +3751,356 @@ function compileOrderBy(orderBy) {
3355
3751
  };
3356
3752
  }
3357
3753
 
3754
+ // src/gateway/structured-select.ts
3755
+ var IDENTIFIER_SEGMENT_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
3756
+ function isIdentifierPath(value) {
3757
+ const segments = value.split(".").map((segment) => segment.trim());
3758
+ return segments.length > 1 && segments.every((segment) => IDENTIFIER_SEGMENT_PATTERN.test(segment));
3759
+ }
3760
+ function extractRelationHead(raw) {
3761
+ const trimmed = raw.trim();
3762
+ if (!trimmed) return "";
3763
+ const aliasIndex = trimmed.indexOf(":");
3764
+ const withoutAlias = aliasIndex >= 0 ? trimmed.slice(aliasIndex + 1).trim() : trimmed;
3765
+ const modifierIndex = withoutAlias.indexOf("!");
3766
+ return (modifierIndex >= 0 ? withoutAlias.slice(0, modifierIndex) : withoutAlias).trim();
3767
+ }
3768
+ function hasSchemaQualifiedRelationToken(select) {
3769
+ let singleQuoted = false;
3770
+ let doubleQuoted = false;
3771
+ let tokenStart = 0;
3772
+ for (let index = 0; index < select.length; index += 1) {
3773
+ const char = select[index];
3774
+ const next = index + 1 < select.length ? select[index + 1] : "";
3775
+ if (singleQuoted) {
3776
+ if (char === "'" && next === "'") {
3777
+ index += 1;
3778
+ continue;
3779
+ }
3780
+ if (char === "'") {
3781
+ singleQuoted = false;
3782
+ }
3783
+ continue;
3784
+ }
3785
+ if (doubleQuoted) {
3786
+ if (char === '"' && next === '"') {
3787
+ index += 1;
3788
+ continue;
3789
+ }
3790
+ if (char === '"') {
3791
+ doubleQuoted = false;
3792
+ }
3793
+ continue;
3794
+ }
3795
+ if (char === "'") {
3796
+ singleQuoted = true;
3797
+ continue;
3798
+ }
3799
+ if (char === '"') {
3800
+ doubleQuoted = true;
3801
+ continue;
3802
+ }
3803
+ if (char === "(") {
3804
+ const relationHead = extractRelationHead(select.slice(tokenStart, index));
3805
+ if (isIdentifierPath(relationHead)) {
3806
+ return true;
3807
+ }
3808
+ tokenStart = index + 1;
3809
+ continue;
3810
+ }
3811
+ if (char === "," || char === ")") {
3812
+ tokenStart = index + 1;
3813
+ }
3814
+ }
3815
+ return false;
3816
+ }
3817
+ function toStructuredSelectString(columns) {
3818
+ return Array.isArray(columns) ? columns.join(",") : columns;
3819
+ }
3820
+ function buildStructuredWhere(conditions) {
3821
+ if (!conditions?.length) return void 0;
3822
+ const where = {};
3823
+ for (const condition of conditions) {
3824
+ if (!condition.column) {
3825
+ return null;
3826
+ }
3827
+ if (condition.value_cast !== void 0) {
3828
+ return null;
3829
+ }
3830
+ const operand = condition.value;
3831
+ const operator = condition.operator;
3832
+ if (operator === "eq") {
3833
+ if (operand === void 0) return null;
3834
+ } else if (operator === "neq" || operator === "gt" || operator === "lt") {
3835
+ if (operand === void 0) return null;
3836
+ } else if (operator === "in") {
3837
+ if (!Array.isArray(operand)) return null;
3838
+ } else {
3839
+ return null;
3840
+ }
3841
+ const existing = where[condition.column];
3842
+ if (existing !== void 0 && (typeof existing !== "object" || existing === null || Array.isArray(existing))) {
3843
+ return null;
3844
+ }
3845
+ const next = existing ?? {};
3846
+ if (Object.prototype.hasOwnProperty.call(next, operator)) {
3847
+ return null;
3848
+ }
3849
+ next[operator] = operand;
3850
+ where[condition.column] = next;
3851
+ }
3852
+ return where;
3853
+ }
3854
+ function buildStructuredOrderBy(order) {
3855
+ if (!order?.field) return void 0;
3856
+ return {
3857
+ [order.field]: order.direction === "descending" ? "desc" : "asc"
3858
+ };
3859
+ }
3860
+ function buildStructuredSelectTransport(input) {
3861
+ const select = toStructuredSelectString(input.columns).trim();
3862
+ if (!select || select === "*") {
3863
+ return null;
3864
+ }
3865
+ if (!hasSchemaQualifiedRelationToken(select)) {
3866
+ return null;
3867
+ }
3868
+ if (input.count !== void 0 || input.head !== void 0) {
3869
+ return {
3870
+ error: "Schema-qualified nested select strings require structured select transport, which does not support count/head options in athena-js yet."
3871
+ };
3872
+ }
3873
+ const where = buildStructuredWhere(input.conditions);
3874
+ if (where === null) {
3875
+ return {
3876
+ error: "Schema-qualified nested select strings only support eq, neq, gt, lt, and in filters in athena-js structured select transport."
3877
+ };
3878
+ }
3879
+ return {
3880
+ select,
3881
+ payload: {
3882
+ table_name: input.tableName,
3883
+ select,
3884
+ where,
3885
+ orderBy: buildStructuredOrderBy(input.order),
3886
+ limit: input.limit,
3887
+ offset: input.offset,
3888
+ strip_nulls: input.stripNulls
3889
+ }
3890
+ };
3891
+ }
3892
+
3893
+ // src/query-transport.ts
3894
+ function canUseFindManyAstTransport(state) {
3895
+ return state.conditions.length === 0 && state.offset === void 0 && state.currentPage === void 0 && state.pageSize === void 0 && state.totalPages === void 0;
3896
+ }
3897
+ function toFindManyAstOrder(order) {
3898
+ if (!order) {
3899
+ return void 0;
3900
+ }
3901
+ return {
3902
+ column: order.field,
3903
+ ascending: order.direction !== "descending"
3904
+ };
3905
+ }
3906
+ function isRecord6(value) {
3907
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
3908
+ }
3909
+ function normalizeFindManyAstColumnPredicate(value) {
3910
+ if (!isRecord6(value)) {
3911
+ return {
3912
+ eq: value
3913
+ };
3914
+ }
3915
+ const normalized = {};
3916
+ for (const [key, operand] of Object.entries(value)) {
3917
+ if (operand !== void 0) {
3918
+ normalized[key] = operand;
3919
+ }
3920
+ }
3921
+ return normalized;
3922
+ }
3923
+ function normalizeFindManyAstBooleanOperand(clause) {
3924
+ const normalized = {};
3925
+ for (const [column, value] of Object.entries(clause)) {
3926
+ if (value === void 0) {
3927
+ continue;
3928
+ }
3929
+ normalized[column] = normalizeFindManyAstColumnPredicate(value);
3930
+ }
3931
+ return normalized;
3932
+ }
3933
+ function normalizeFindManyAstWhere(where) {
3934
+ if (!where || !isRecord6(where)) {
3935
+ return where;
3936
+ }
3937
+ const normalized = {};
3938
+ for (const [key, value] of Object.entries(where)) {
3939
+ if (value === void 0) {
3940
+ continue;
3941
+ }
3942
+ if (key === "or" && Array.isArray(value)) {
3943
+ normalized.or = value.map(
3944
+ (clause) => normalizeFindManyAstBooleanOperand(clause)
3945
+ );
3946
+ continue;
3947
+ }
3948
+ if (key === "not" && isRecord6(value)) {
3949
+ normalized.not = normalizeFindManyAstBooleanOperand(
3950
+ value
3951
+ );
3952
+ continue;
3953
+ }
3954
+ normalized[key] = normalizeFindManyAstColumnPredicate(value);
3955
+ }
3956
+ return normalized;
3957
+ }
3958
+ function predicateRequiresUuidQueryFallback(column, value) {
3959
+ if (!isRecord6(value)) {
3960
+ return shouldUseUuidTextComparison(column, value);
3961
+ }
3962
+ const eqValue = value.eq;
3963
+ return eqValue !== void 0 && shouldUseUuidTextComparison(column, eqValue);
3964
+ }
3965
+ function booleanOperandRequiresUuidQueryFallback(clause) {
3966
+ for (const [column, value] of Object.entries(clause)) {
3967
+ if (value === void 0) {
3968
+ continue;
3969
+ }
3970
+ if (predicateRequiresUuidQueryFallback(column, value)) {
3971
+ return true;
3972
+ }
3973
+ }
3974
+ return false;
3975
+ }
3976
+ function findManyAstWhereRequiresLegacyTransport(where) {
3977
+ if (!where || !isRecord6(where)) {
3978
+ return false;
3979
+ }
3980
+ for (const [key, value] of Object.entries(where)) {
3981
+ if (value === void 0) {
3982
+ continue;
3983
+ }
3984
+ if (key === "or" && Array.isArray(value)) {
3985
+ if (value.some(
3986
+ (clause) => booleanOperandRequiresUuidQueryFallback(clause)
3987
+ )) {
3988
+ return true;
3989
+ }
3990
+ continue;
3991
+ }
3992
+ if (key === "not" && isRecord6(value)) {
3993
+ if (booleanOperandRequiresUuidQueryFallback(value)) {
3994
+ return true;
3995
+ }
3996
+ continue;
3997
+ }
3998
+ if (predicateRequiresUuidQueryFallback(key, value)) {
3999
+ return true;
4000
+ }
4001
+ }
4002
+ return false;
4003
+ }
4004
+ function resolvePagination(input) {
4005
+ let limit = input.limit;
4006
+ let offset = input.offset;
4007
+ if (limit === void 0 && input.pageSize !== void 0) {
4008
+ limit = Math.max(0, Math.trunc(input.pageSize));
4009
+ }
4010
+ if (offset === void 0 && input.pageSize !== void 0 && input.currentPage !== void 0 && input.currentPage > 0) {
4011
+ offset = (Math.trunc(input.currentPage) - 1) * Math.max(0, Math.trunc(input.pageSize));
4012
+ }
4013
+ return { limit, offset };
4014
+ }
4015
+ function hasTypedEqualityComparison(conditions) {
4016
+ return conditions?.some(
4017
+ (condition) => condition.operator === "eq" && (condition.value_cast !== void 0 || condition.column_cast !== void 0)
4018
+ ) ?? false;
4019
+ }
4020
+ function createSelectTransportPlan(input) {
4021
+ const conditions = input.state.conditions.length ? input.state.conditions.map((condition) => ({ ...condition })) : void 0;
4022
+ const pagination = resolvePagination({
4023
+ limit: input.state.limit,
4024
+ offset: input.state.offset,
4025
+ currentPage: input.state.currentPage,
4026
+ pageSize: input.state.pageSize
4027
+ });
4028
+ const stripNulls = input.options?.stripNulls ?? true;
4029
+ const structuredSelectTransport = buildStructuredSelectTransport({
4030
+ tableName: input.tableName,
4031
+ columns: input.columns,
4032
+ conditions,
4033
+ limit: pagination.limit,
4034
+ offset: pagination.offset,
4035
+ order: input.state.order,
4036
+ stripNulls,
4037
+ count: input.options?.count,
4038
+ head: input.options?.head
4039
+ });
4040
+ if (structuredSelectTransport && "error" in structuredSelectTransport) {
4041
+ throw new Error(structuredSelectTransport.error);
4042
+ }
4043
+ if (structuredSelectTransport) {
4044
+ const { payload, select } = structuredSelectTransport;
4045
+ return {
4046
+ kind: "fetch",
4047
+ payload,
4048
+ debug: {
4049
+ columns: select,
4050
+ conditions,
4051
+ limit: pagination.limit,
4052
+ offset: pagination.offset,
4053
+ order: input.state.order
4054
+ }
4055
+ };
4056
+ }
4057
+ if (hasTypedEqualityComparison(conditions) && !input.options?.head && !input.options?.count && conditions) {
4058
+ const query = input.buildTypedSelectQuery({
4059
+ tableName: input.tableName,
4060
+ columns: input.columns,
4061
+ conditions,
4062
+ limit: input.state.limit,
4063
+ offset: input.state.offset,
4064
+ currentPage: input.state.currentPage,
4065
+ pageSize: input.state.pageSize,
4066
+ order: input.state.order
4067
+ });
4068
+ if (query) {
4069
+ return {
4070
+ kind: "query",
4071
+ query,
4072
+ payload: { query }
4073
+ };
4074
+ }
4075
+ }
4076
+ return {
4077
+ kind: "fetch",
4078
+ payload: {
4079
+ table_name: input.tableName,
4080
+ columns: input.columns,
4081
+ conditions,
4082
+ limit: input.state.limit,
4083
+ offset: input.state.offset,
4084
+ current_page: input.state.currentPage,
4085
+ page_size: input.state.pageSize,
4086
+ total_pages: input.state.totalPages,
4087
+ sort_by: input.state.order,
4088
+ strip_nulls: stripNulls,
4089
+ count: input.options?.count,
4090
+ head: input.options?.head
4091
+ },
4092
+ debug: {
4093
+ columns: input.columns,
4094
+ conditions,
4095
+ limit: input.state.limit,
4096
+ offset: input.state.offset,
4097
+ currentPage: input.state.currentPage,
4098
+ pageSize: input.state.pageSize,
4099
+ order: input.state.order
4100
+ }
4101
+ };
4102
+ }
4103
+
3358
4104
  // src/client.ts
3359
4105
  var DEFAULT_COLUMNS = "*";
3360
4106
  var SAFE_CAST_PATTERN = /^[a-z_][a-z0-9_]*(?:\[\])?$/i;
@@ -3369,18 +4115,6 @@ var QUERY_TRACE_STACK_SKIP_PATTERNS = [
3369
4115
  "node:internal",
3370
4116
  "internal/process"
3371
4117
  ];
3372
- function canUseFindManyAstTransport(state) {
3373
- return state.conditions.length === 0 && state.offset === void 0 && state.currentPage === void 0 && state.pageSize === void 0 && state.totalPages === void 0;
3374
- }
3375
- function toFindManyAstOrder(order) {
3376
- if (!order) {
3377
- return void 0;
3378
- }
3379
- return {
3380
- column: order.field,
3381
- ascending: order.direction !== "descending"
3382
- };
3383
- }
3384
4118
  function formatResult(response) {
3385
4119
  const result = {
3386
4120
  data: response.data ?? null,
@@ -3395,6 +4129,13 @@ function formatResult(response) {
3395
4129
  }
3396
4130
  return result;
3397
4131
  }
4132
+ var EXPERIMENTAL_READ_RETRY_CONFIG = {
4133
+ retries: 2,
4134
+ baseDelayMs: 100,
4135
+ maxDelayMs: 1e3,
4136
+ backoff: "exponential",
4137
+ jitter: true
4138
+ };
3398
4139
  function attachNormalizedError(result, normalizedError) {
3399
4140
  Object.defineProperty(result, ATHENA_NORMALIZED_ERROR_KEY, {
3400
4141
  value: normalizedError,
@@ -3421,7 +4162,36 @@ function createResultFormatter(experimental) {
3421
4162
  return result;
3422
4163
  };
3423
4164
  }
3424
- function isRecord6(value) {
4165
+ async function executeExperimentalRead(experimental, runner) {
4166
+ if (!experimental?.retryReads) {
4167
+ return runner();
4168
+ }
4169
+ let lastRetryableResult;
4170
+ let lastRetrySignal = null;
4171
+ try {
4172
+ return await withRetry(
4173
+ {
4174
+ ...EXPERIMENTAL_READ_RETRY_CONFIG,
4175
+ shouldRetry: (error) => error === lastRetrySignal || normalizeAthenaError(error).retryable
4176
+ },
4177
+ async () => {
4178
+ const result = await runner();
4179
+ if (result.error?.retryable) {
4180
+ lastRetryableResult = result;
4181
+ lastRetrySignal = result.error;
4182
+ throw lastRetrySignal;
4183
+ }
4184
+ return result;
4185
+ }
4186
+ );
4187
+ } catch (error) {
4188
+ if (lastRetryableResult && error === lastRetrySignal) {
4189
+ return lastRetryableResult;
4190
+ }
4191
+ throw error;
4192
+ }
4193
+ }
4194
+ function isRecord7(value) {
3425
4195
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
3426
4196
  }
3427
4197
  function firstNonEmptyString2(...values) {
@@ -3433,8 +4203,8 @@ function firstNonEmptyString2(...values) {
3433
4203
  return void 0;
3434
4204
  }
3435
4205
  function resolveStructuredErrorPayload2(raw) {
3436
- if (!isRecord6(raw)) return null;
3437
- return isRecord6(raw.error) ? raw.error : raw;
4206
+ if (!isRecord7(raw)) return null;
4207
+ return isRecord7(raw.error) ? raw.error : raw;
3438
4208
  }
3439
4209
  function resolveStructuredErrorDetails(payload, message) {
3440
4210
  if (!payload || !("details" in payload)) {
@@ -3450,7 +4220,7 @@ function resolveStructuredErrorDetails(payload, message) {
3450
4220
  return details;
3451
4221
  }
3452
4222
  function createResultError(response, result, normalized) {
3453
- const rawRecord = isRecord6(response.raw) ? response.raw : null;
4223
+ const rawRecord = isRecord7(response.raw) ? response.raw : null;
3454
4224
  const payload = resolveStructuredErrorPayload2(response.raw);
3455
4225
  const message = firstNonEmptyString2(
3456
4226
  response.error,
@@ -3645,7 +4415,14 @@ function toSingleResult(response) {
3645
4415
  function mergeOptions(...options) {
3646
4416
  return options.reduce((acc, next) => {
3647
4417
  if (!next) return acc;
3648
- return { ...acc, ...next };
4418
+ const merged = { ...acc ?? {}, ...next };
4419
+ if (acc?.headers || next.headers) {
4420
+ merged.headers = {
4421
+ ...acc?.headers ?? {},
4422
+ ...next.headers ?? {}
4423
+ };
4424
+ }
4425
+ return merged;
3649
4426
  }, void 0);
3650
4427
  }
3651
4428
  function asAthenaJsonObject(value) {
@@ -3926,17 +4703,6 @@ function conditionToDebugSqlClause(condition) {
3926
4703
  return `TRUE /* unsupported condition: ${rawCondition} */`;
3927
4704
  }
3928
4705
  }
3929
- function resolvePagination(input) {
3930
- let limit = input.limit;
3931
- let offset = input.offset;
3932
- if (limit === void 0 && input.pageSize !== void 0) {
3933
- limit = input.pageSize;
3934
- }
3935
- if (offset === void 0 && input.pageSize !== void 0 && input.currentPage !== void 0 && input.currentPage > 0) {
3936
- offset = (input.currentPage - 1) * input.pageSize;
3937
- }
3938
- return { limit, offset };
3939
- }
3940
4706
  function appendOrderLimitOffset(sqlParts, order, limit, offset) {
3941
4707
  if (order?.field) {
3942
4708
  const direction = order.direction === "descending" ? "DESC" : "ASC";
@@ -4440,80 +5206,56 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
4440
5206
  );
4441
5207
  const runSelect = async (columns = DEFAULT_COLUMNS, options, executionState = snapshotState(), callsite) => {
4442
5208
  const resolvedTableName = resolveTableNameForCall(tableName, options?.schema);
4443
- const conditions = executionState.conditions.length ? executionState.conditions.map((condition) => ({ ...condition })) : void 0;
4444
- const hasTypedEqualityComparison = conditions?.some(
4445
- (condition) => condition.operator === "eq" && (condition.value_cast !== void 0 || condition.column_cast !== void 0)
4446
- ) ?? false;
4447
- if (hasTypedEqualityComparison && !options?.head && !options?.count && conditions) {
4448
- const query = buildTypedSelectQuery({
4449
- tableName: resolvedTableName,
4450
- columns,
4451
- conditions,
4452
- limit: executionState.limit,
4453
- offset: executionState.offset,
4454
- currentPage: executionState.currentPage,
4455
- pageSize: executionState.pageSize,
4456
- order: executionState.order
4457
- });
4458
- if (query) {
4459
- const payload2 = { query };
4460
- return executeWithQueryTrace(
5209
+ const plan = createSelectTransportPlan({
5210
+ tableName: resolvedTableName,
5211
+ columns,
5212
+ state: executionState,
5213
+ options,
5214
+ buildTypedSelectQuery
5215
+ });
5216
+ if (plan.kind === "query") {
5217
+ return executeExperimentalRead(
5218
+ experimental,
5219
+ () => executeWithQueryTrace(
4461
5220
  tracer,
4462
5221
  {
4463
5222
  operation: "select",
4464
5223
  endpoint: "/gateway/query",
4465
5224
  table: resolvedTableName,
4466
- sql: query,
4467
- payload: payload2,
5225
+ sql: plan.query,
5226
+ payload: plan.payload,
4468
5227
  options
4469
5228
  },
4470
5229
  async () => {
4471
- const queryResponse = await client.queryGateway(payload2, options);
5230
+ const queryResponse = await client.queryGateway(plan.payload, options);
4472
5231
  return formatGatewayResult(queryResponse, { table: resolvedTableName, operation: "select" });
4473
5232
  },
4474
5233
  callsite
4475
- );
4476
- }
5234
+ )
5235
+ );
4477
5236
  }
4478
- const payload = {
4479
- table_name: resolvedTableName,
4480
- columns,
4481
- conditions,
4482
- limit: executionState.limit,
4483
- offset: executionState.offset,
4484
- current_page: executionState.currentPage,
4485
- page_size: executionState.pageSize,
4486
- total_pages: executionState.totalPages,
4487
- sort_by: executionState.order,
4488
- strip_nulls: options?.stripNulls ?? true,
4489
- count: options?.count,
4490
- head: options?.head
4491
- };
4492
5237
  const sql = buildDebugSelectQuery({
4493
5238
  tableName: resolvedTableName,
4494
- columns,
4495
- conditions,
4496
- limit: executionState.limit,
4497
- offset: executionState.offset,
4498
- currentPage: executionState.currentPage,
4499
- pageSize: executionState.pageSize,
4500
- order: executionState.order
5239
+ ...plan.debug
4501
5240
  });
4502
- return executeWithQueryTrace(
4503
- tracer,
4504
- {
4505
- operation: "select",
4506
- endpoint: "/gateway/fetch",
4507
- table: resolvedTableName,
4508
- sql,
4509
- payload,
4510
- options
4511
- },
4512
- async () => {
4513
- const response = await client.fetchGateway(payload, options);
4514
- return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
4515
- },
4516
- callsite
5241
+ return executeExperimentalRead(
5242
+ experimental,
5243
+ () => executeWithQueryTrace(
5244
+ tracer,
5245
+ {
5246
+ operation: "select",
5247
+ endpoint: "/gateway/fetch",
5248
+ table: resolvedTableName,
5249
+ sql,
5250
+ payload: plan.payload,
5251
+ options
5252
+ },
5253
+ async () => {
5254
+ const response = await client.fetchGateway(plan.payload, options);
5255
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
5256
+ },
5257
+ callsite
5258
+ )
4517
5259
  );
4518
5260
  };
4519
5261
  const createSelectChain = (columns, options, initialCallsite) => {
@@ -4583,14 +5325,14 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
4583
5325
  if (options.limit !== void 0) {
4584
5326
  executionState.limit = options.limit;
4585
5327
  }
4586
- if (experimental?.findManyAst && canUseFindManyAstTransport(baseState)) {
5328
+ if (experimental?.findManyAst && canUseFindManyAstTransport(baseState) && !selectShapeUsesRelationSchema(options.select) && !findManyAstWhereRequiresLegacyTransport(options.where)) {
4587
5329
  const resolvedTableName = resolveTableNameForCall(tableName, void 0);
4588
5330
  const payload = {
4589
5331
  table_name: resolvedTableName,
4590
5332
  select: options.select
4591
5333
  };
4592
5334
  if (options.where !== void 0) {
4593
- payload.where = options.where;
5335
+ payload.where = normalizeFindManyAstWhere(options.where);
4594
5336
  }
4595
5337
  const astOrder = toFindManyAstOrder(executionState.order);
4596
5338
  if (astOrder !== void 0) {
@@ -4606,22 +5348,25 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
4606
5348
  limit: executionState.limit,
4607
5349
  order: executionState.order
4608
5350
  });
4609
- return executeWithQueryTrace(
4610
- tracer,
4611
- {
4612
- operation: "select",
4613
- endpoint: "/gateway/fetch",
4614
- table: resolvedTableName,
4615
- sql,
4616
- payload
4617
- },
4618
- async () => {
4619
- const response = await client.fetchGateway(
5351
+ return executeExperimentalRead(
5352
+ experimental,
5353
+ () => executeWithQueryTrace(
5354
+ tracer,
5355
+ {
5356
+ operation: "select",
5357
+ endpoint: "/gateway/fetch",
5358
+ table: resolvedTableName,
5359
+ sql,
4620
5360
  payload
4621
- );
4622
- return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
4623
- },
4624
- callsite
5361
+ },
5362
+ async () => {
5363
+ const response = await client.fetchGateway(
5364
+ payload
5365
+ );
5366
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
5367
+ },
5368
+ callsite
5369
+ )
4625
5370
  );
4626
5371
  }
4627
5372
  return runSelect(
@@ -4869,7 +5614,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
4869
5614
  });
4870
5615
  return builder;
4871
5616
  }
4872
- function createQueryBuilder(client, formatGatewayResult, tracer) {
5617
+ function createQueryBuilder(client, formatGatewayResult, experimental, tracer) {
4873
5618
  return async function query(query, options) {
4874
5619
  const normalizedQuery = query.trim();
4875
5620
  if (!normalizedQuery) {
@@ -4877,35 +5622,50 @@ function createQueryBuilder(client, formatGatewayResult, tracer) {
4877
5622
  }
4878
5623
  const payload = { query: normalizedQuery };
4879
5624
  const callsite = captureTraceCallsite(tracer);
4880
- return executeWithQueryTrace(
4881
- tracer,
4882
- {
4883
- operation: "query",
4884
- endpoint: "/gateway/query",
4885
- sql: normalizedQuery,
4886
- payload,
4887
- options
4888
- },
4889
- async () => {
4890
- const response = await client.queryGateway(payload, options);
4891
- return formatGatewayResult(response, { operation: "query" });
4892
- },
4893
- callsite
5625
+ return executeExperimentalRead(
5626
+ experimental,
5627
+ () => executeWithQueryTrace(
5628
+ tracer,
5629
+ {
5630
+ operation: "query",
5631
+ endpoint: "/gateway/query",
5632
+ sql: normalizedQuery,
5633
+ payload,
5634
+ options
5635
+ },
5636
+ async () => {
5637
+ const response = await client.queryGateway(payload, options);
5638
+ return formatGatewayResult(response, { operation: "query" });
5639
+ },
5640
+ callsite
5641
+ )
4894
5642
  );
4895
5643
  };
4896
5644
  }
4897
5645
  function createClientFromConfig(config) {
5646
+ const gatewayHeaders = {
5647
+ ...config.headers ?? {}
5648
+ };
5649
+ if (config.auth?.bearerToken && gatewayHeaders["X-Athena-Auth-Bearer-Token"] === void 0 && gatewayHeaders["x-athena-auth-bearer-token"] === void 0) {
5650
+ gatewayHeaders["X-Athena-Auth-Bearer-Token"] = config.auth.bearerToken;
5651
+ }
4898
5652
  const gateway = createAthenaGatewayClient({
4899
5653
  baseUrl: config.baseUrl,
4900
5654
  apiKey: config.apiKey,
4901
5655
  client: config.client,
4902
5656
  backend: config.backend,
4903
- headers: config.headers
5657
+ headers: gatewayHeaders
4904
5658
  });
4905
5659
  const formatGatewayResult = createResultFormatter();
4906
5660
  const queryTracer = createQueryTracer(config.experimental);
4907
5661
  const auth = createAuthClient(config.auth);
4908
- const from = (table) => createTableBuilder(table, gateway, formatGatewayResult, queryTracer, config.experimental);
5662
+ const from = (table, options) => createTableBuilder(
5663
+ resolveTableNameForCall(table, options?.schema),
5664
+ gateway,
5665
+ formatGatewayResult,
5666
+ queryTracer,
5667
+ config.experimental
5668
+ );
4909
5669
  const rpc = (fn, args, options) => {
4910
5670
  const normalizedFn = fn.trim();
4911
5671
  if (!normalizedFn) {
@@ -4921,13 +5681,14 @@ function createClientFromConfig(config) {
4921
5681
  captureTraceCallsite(queryTracer)
4922
5682
  );
4923
5683
  };
4924
- const query = createQueryBuilder(gateway, formatGatewayResult, queryTracer);
5684
+ const query = createQueryBuilder(gateway, formatGatewayResult, config.experimental, queryTracer);
4925
5685
  const db = createDbModule({ from, rpc, query });
4926
5686
  return {
4927
5687
  from,
4928
5688
  db,
4929
5689
  rpc,
4930
5690
  query,
5691
+ verifyConnection: gateway.verifyConnection,
4931
5692
  auth: auth.auth
4932
5693
  };
4933
5694
  }