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