@xylex-group/athena 2.3.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +124 -106
  2. package/dist/browser.cjs +584 -99
  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 +583 -100
  7. package/dist/browser.js.map +1 -1
  8. package/dist/cli/index.cjs +573 -97
  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 +573 -97
  13. package/dist/cli/index.js.map +1 -1
  14. package/dist/index.cjs +584 -99
  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 +583 -100
  19. package/dist/index.js.map +1 -1
  20. package/dist/{model-form-BpDXlbxb.d.ts → model-form-C0FAbOaf.d.ts} +1 -1
  21. package/dist/{model-form-hoE2jHIi.d.cts → model-form-GzTqhEzM.d.cts} +1 -1
  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-BvyCZnfW.d.cts → react-email-BuApZuyG.d.ts} +19 -6
  25. package/dist/{react-email-qPA1wjFV.d.ts → react-email-CQJq92zQ.d.cts} +19 -6
  26. package/dist/react.cjs +249 -12
  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 +249 -12
  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/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
  }
@@ -1359,8 +1363,74 @@ function generateArtifactsFromSnapshot(snapshot, config) {
1359
1363
  return new ArtifactComposer(snapshot, normalizedConfig).compose();
1360
1364
  }
1361
1365
 
1366
+ // src/gateway/url.ts
1367
+ var ATHENA_DEFAULT_BASE_URL = "https://athena-db.com";
1368
+ function describeReceivedValue(value) {
1369
+ if (value === void 0) return "undefined";
1370
+ if (value === null) return "null";
1371
+ if (typeof value === "string") {
1372
+ return value.trim().length > 0 ? JSON.stringify(value) : "an empty string";
1373
+ }
1374
+ return `${typeof value} ${JSON.stringify(value)}`;
1375
+ }
1376
+ function invalidBaseUrlError(message, hint) {
1377
+ return new AthenaGatewayError({
1378
+ code: "INVALID_URL",
1379
+ message,
1380
+ status: 0,
1381
+ hint
1382
+ });
1383
+ }
1384
+ function normalizeAthenaGatewayBaseUrl(input, options = {}) {
1385
+ const label = options.label ?? "Athena gateway base URL";
1386
+ const candidate = input ?? options.defaultBaseUrl;
1387
+ if (candidate === void 0 || candidate === null) {
1388
+ throw invalidBaseUrlError(
1389
+ `${label} must be a non-empty absolute http(s) URL. Received ${describeReceivedValue(input)}.`,
1390
+ 'Set ATHENA_URL (or pass createClient(url, ...)) to a full URL such as "https://mirror3.athena-db.com".'
1391
+ );
1392
+ }
1393
+ const trimmed = candidate.trim();
1394
+ if (!trimmed) {
1395
+ throw invalidBaseUrlError(
1396
+ `${label} must be a non-empty absolute http(s) URL. Received ${describeReceivedValue(candidate)}.`,
1397
+ 'Set ATHENA_URL (or pass createClient(url, ...)) to a full URL such as "https://mirror3.athena-db.com".'
1398
+ );
1399
+ }
1400
+ let parsed;
1401
+ try {
1402
+ parsed = new URL(trimmed);
1403
+ } catch {
1404
+ throw invalidBaseUrlError(
1405
+ `${label} must be a valid absolute http(s) URL. Received ${describeReceivedValue(candidate)}.`,
1406
+ 'Use a full URL including the protocol, for example "https://mirror3.athena-db.com".'
1407
+ );
1408
+ }
1409
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
1410
+ throw invalidBaseUrlError(
1411
+ `${label} must use http or https. Received ${JSON.stringify(trimmed)}.`,
1412
+ 'Use an Athena gateway URL such as "https://mirror3.athena-db.com".'
1413
+ );
1414
+ }
1415
+ if (parsed.search || parsed.hash) {
1416
+ throw invalidBaseUrlError(
1417
+ `${label} must not include query parameters or hash fragments. Received ${JSON.stringify(trimmed)}.`,
1418
+ 'Pass only the base URL. Endpoint paths such as "/gateway/fetch" are appended by the SDK.'
1419
+ );
1420
+ }
1421
+ return parsed.toString().replace(/\/+$/, "");
1422
+ }
1423
+ function buildAthenaGatewayUrl(baseUrl, path) {
1424
+ if (!path.startsWith("/")) {
1425
+ throw invalidBaseUrlError(
1426
+ `Athena gateway path must start with "/". Received ${JSON.stringify(path)}.`,
1427
+ 'Use a leading slash such as "/gateway/fetch" or "/".'
1428
+ );
1429
+ }
1430
+ return `${baseUrl}${path}`;
1431
+ }
1432
+
1362
1433
  // src/gateway/client.ts
1363
- var DEFAULT_BASE_URL = "https://athena-db.com";
1364
1434
  var DEFAULT_CLIENT = "railway_direct";
1365
1435
  var FALLBACK_SDK_VERSION = "1.3.0";
1366
1436
  var SDK_NAME = "xylex-group/athena";
@@ -1557,9 +1627,168 @@ function buildHeaders(config, options) {
1557
1627
  });
1558
1628
  return headers;
1559
1629
  }
1630
+ function toInvalidUrlResponse(error, endpoint, method) {
1631
+ const message = error instanceof Error ? error.message : String(error);
1632
+ const gatewayError = error instanceof AthenaGatewayError ? error : new AthenaGatewayError({
1633
+ code: "INVALID_URL",
1634
+ message,
1635
+ status: 0,
1636
+ endpoint,
1637
+ method,
1638
+ cause: message,
1639
+ hint: "Set ATHENA_URL to a full http(s) URL before running queries."
1640
+ });
1641
+ return {
1642
+ ok: false,
1643
+ status: 0,
1644
+ statusText: null,
1645
+ data: null,
1646
+ error: gatewayError.message,
1647
+ errorDetails: detailsFromError(
1648
+ new AthenaGatewayError({
1649
+ code: gatewayError.code,
1650
+ message: gatewayError.message,
1651
+ status: gatewayError.status,
1652
+ endpoint,
1653
+ method,
1654
+ requestId: gatewayError.requestId,
1655
+ hint: gatewayError.hint,
1656
+ cause: gatewayError.causeDetail
1657
+ })
1658
+ ),
1659
+ raw: null
1660
+ };
1661
+ }
1662
+ function resolveGatewayBaseUrl(input) {
1663
+ return normalizeAthenaGatewayBaseUrl(input, {
1664
+ defaultBaseUrl: ATHENA_DEFAULT_BASE_URL
1665
+ });
1666
+ }
1667
+ function resolveProbePath(path) {
1668
+ if (!path) return "/";
1669
+ if (!path.startsWith("/")) {
1670
+ throw new AthenaGatewayError({
1671
+ code: "INVALID_URL",
1672
+ message: `Athena gateway probe path must start with "/". Received ${JSON.stringify(path)}.`,
1673
+ status: 0,
1674
+ hint: 'Use a leading slash such as "/" or "/health".'
1675
+ });
1676
+ }
1677
+ return path;
1678
+ }
1679
+ function mergeConnectionHeaders(baseHeaders, headers) {
1680
+ const merged = {
1681
+ ...baseHeaders,
1682
+ ...headers ?? {}
1683
+ };
1684
+ if (!merged["X-Athena-Sdk"] && !merged["x-athena-sdk"]) {
1685
+ merged["X-Athena-Sdk"] = SDK_HEADER_VALUE;
1686
+ }
1687
+ return merged;
1688
+ }
1689
+ async function performConnectionCheck(baseUrl, requestHeaders, options) {
1690
+ const path = resolveProbePath(options?.path);
1691
+ const url = buildAthenaGatewayUrl(baseUrl, path);
1692
+ try {
1693
+ const response = await fetch(url, {
1694
+ method: "GET",
1695
+ headers: mergeConnectionHeaders(requestHeaders, options?.headers),
1696
+ signal: options?.signal
1697
+ });
1698
+ const rawText = await response.text();
1699
+ const requestId = resolveRequestId(response.headers);
1700
+ const parsedBody = parseResponseBody(
1701
+ rawText ?? "",
1702
+ response.headers.get("content-type")
1703
+ );
1704
+ if (parsedBody.parseFailed) {
1705
+ const invalidJsonError = new AthenaGatewayError({
1706
+ code: "INVALID_JSON",
1707
+ message: "Gateway probe returned malformed JSON",
1708
+ status: response.status,
1709
+ method: "GET",
1710
+ requestId,
1711
+ hint: "Verify the gateway response body is valid JSON.",
1712
+ cause: rawText.slice(0, 300)
1713
+ });
1714
+ return {
1715
+ ok: false,
1716
+ reachable: true,
1717
+ status: response.status,
1718
+ statusText: resolveStatusText(response, parsedBody.parsed),
1719
+ baseUrl,
1720
+ url,
1721
+ error: invalidJsonError.message,
1722
+ errorDetails: detailsFromError(invalidJsonError),
1723
+ raw: parsedBody.parsed
1724
+ };
1725
+ }
1726
+ const parsed = parsedBody.parsed;
1727
+ if (!response.ok) {
1728
+ const httpError = new AthenaGatewayError({
1729
+ code: "HTTP_ERROR",
1730
+ message: resolveErrorMessage(
1731
+ parsed,
1732
+ `Athena gateway GET ${path} failed with status ${response.status}`
1733
+ ),
1734
+ status: response.status,
1735
+ method: "GET",
1736
+ requestId,
1737
+ hint: resolveErrorHint(parsed)
1738
+ });
1739
+ return {
1740
+ ok: false,
1741
+ reachable: true,
1742
+ status: response.status,
1743
+ statusText: resolveStatusText(response, parsed),
1744
+ baseUrl,
1745
+ url,
1746
+ error: httpError.message,
1747
+ errorDetails: detailsFromError(httpError),
1748
+ raw: parsed
1749
+ };
1750
+ }
1751
+ return {
1752
+ ok: true,
1753
+ reachable: true,
1754
+ status: response.status,
1755
+ statusText: resolveStatusText(response, parsed),
1756
+ baseUrl,
1757
+ url,
1758
+ error: void 0,
1759
+ errorDetails: null,
1760
+ raw: parsed
1761
+ };
1762
+ } catch (callError) {
1763
+ const message = callError instanceof Error ? callError.message : String(callError);
1764
+ const networkError = new AthenaGatewayError({
1765
+ code: "NETWORK_ERROR",
1766
+ message: `Network error while probing Athena gateway ${url}: ${message}`,
1767
+ method: "GET",
1768
+ cause: message,
1769
+ hint: "Check gateway URL, DNS, and network reachability."
1770
+ });
1771
+ return {
1772
+ ok: false,
1773
+ reachable: false,
1774
+ status: 0,
1775
+ statusText: null,
1776
+ baseUrl,
1777
+ url,
1778
+ error: networkError.message,
1779
+ errorDetails: detailsFromError(networkError),
1780
+ raw: null
1781
+ };
1782
+ }
1783
+ }
1560
1784
  async function callAthena(config, endpoint, method, payload, options) {
1561
- const baseUrl = (options?.baseUrl ?? config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
1562
- const url = `${baseUrl}${endpoint}`;
1785
+ let baseUrl;
1786
+ try {
1787
+ baseUrl = resolveGatewayBaseUrl(options?.baseUrl ?? config.baseUrl);
1788
+ } catch (error) {
1789
+ return toInvalidUrlResponse(error, endpoint, method);
1790
+ }
1791
+ const url = buildAthenaGatewayUrl(baseUrl, endpoint);
1563
1792
  const headers = buildHeaders(config, options);
1564
1793
  try {
1565
1794
  const requestInit = {
@@ -1656,32 +1885,44 @@ async function callAthena(config, endpoint, method, payload, options) {
1656
1885
  }
1657
1886
  }
1658
1887
  function createAthenaGatewayClient(config = {}) {
1888
+ const normalizedBaseUrl = resolveGatewayBaseUrl(config.baseUrl);
1889
+ const normalizedConfig = {
1890
+ ...config,
1891
+ baseUrl: normalizedBaseUrl
1892
+ };
1659
1893
  return {
1660
- baseUrl: (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, ""),
1894
+ baseUrl: normalizedBaseUrl,
1661
1895
  buildHeaders(options) {
1662
- return buildHeaders(config, options);
1896
+ return buildHeaders(normalizedConfig, options);
1897
+ },
1898
+ verifyConnection(options) {
1899
+ return performConnectionCheck(
1900
+ normalizedBaseUrl,
1901
+ buildHeaders(normalizedConfig),
1902
+ options
1903
+ );
1663
1904
  },
1664
1905
  fetchGateway(payload, options) {
1665
- return callAthena(config, "/gateway/fetch", "POST", payload, options);
1906
+ return callAthena(normalizedConfig, "/gateway/fetch", "POST", payload, options);
1666
1907
  },
1667
1908
  insertGateway(payload, options) {
1668
- return callAthena(config, "/gateway/insert", "PUT", payload, options);
1909
+ return callAthena(normalizedConfig, "/gateway/insert", "PUT", payload, options);
1669
1910
  },
1670
1911
  updateGateway(payload, options) {
1671
- return callAthena(config, "/gateway/update", "POST", payload, options);
1912
+ return callAthena(normalizedConfig, "/gateway/update", "POST", payload, options);
1672
1913
  },
1673
1914
  deleteGateway(payload, options) {
1674
- return callAthena(config, "/gateway/delete", "DELETE", payload, options);
1915
+ return callAthena(normalizedConfig, "/gateway/delete", "DELETE", payload, options);
1675
1916
  },
1676
1917
  rpcGateway(payload, options) {
1677
1918
  if (options?.get) {
1678
1919
  const endpoint = buildRpcGetEndpoint(payload);
1679
- return callAthena(config, endpoint, "GET", null, options);
1920
+ return callAthena(normalizedConfig, endpoint, "GET", null, options);
1680
1921
  }
1681
- return callAthena(config, "/gateway/rpc", "POST", payload, options);
1922
+ return callAthena(normalizedConfig, "/gateway/rpc", "POST", payload, options);
1682
1923
  },
1683
1924
  queryGateway(payload, options) {
1684
- return callAthena(config, "/gateway/query", "POST", payload, options);
1925
+ return callAthena(normalizedConfig, "/gateway/query", "POST", payload, options);
1685
1926
  }
1686
1927
  };
1687
1928
  }
@@ -3086,8 +3327,8 @@ function createAuthClient(config = {}) {
3086
3327
  // src/db/module.ts
3087
3328
  function createDbModule(input) {
3088
3329
  const db = {
3089
- from(table) {
3090
- return input.from(table);
3330
+ from(table, options) {
3331
+ return input.from(table, options);
3091
3332
  },
3092
3333
  select(table, columns, options) {
3093
3334
  return input.from(table).select(columns, options);
@@ -3192,7 +3433,19 @@ function buildGatewayCondition(operator, column, value) {
3192
3433
  function compileRelationToken(key, node) {
3193
3434
  const nested = compileSelectShape(node.select);
3194
3435
  const propertyKey = normalizeIdentifier(key, "select relation key");
3195
- const relationToken = normalizeIdentifier(node.via ?? propertyKey, "select relation token");
3436
+ if (node.schema && node.via) {
3437
+ throw new Error(
3438
+ `findMany relation "${propertyKey}" cannot combine schema and via yet; use schema with the relation key, or use via without schema`
3439
+ );
3440
+ }
3441
+ const relationTokenBase = normalizeIdentifier(node.via ?? propertyKey, "select relation token");
3442
+ if (node.schema && relationTokenBase.includes(".")) {
3443
+ throw new Error(
3444
+ `findMany relation "${propertyKey}" already resolves to a qualified relation token; do not also set schema`
3445
+ );
3446
+ }
3447
+ const relationSchema = node.schema?.trim();
3448
+ const relationToken = relationSchema ? `${normalizeIdentifier(relationSchema, "select relation schema")}.${relationTokenBase}` : relationTokenBase;
3196
3449
  const alias = node.as?.trim() || (relationToken !== propertyKey ? propertyKey : "");
3197
3450
  const prefix = alias ? `${alias}:` : "";
3198
3451
  return `${prefix}${relationToken}(${nested})`;
@@ -3221,6 +3474,23 @@ function compileSelectShape(select) {
3221
3474
  }
3222
3475
  return tokens.join(",");
3223
3476
  }
3477
+ function selectShapeUsesRelationSchema(select) {
3478
+ if (!isRecord5(select)) {
3479
+ return false;
3480
+ }
3481
+ for (const rawValue of Object.values(select)) {
3482
+ if (!isRelationSelectNode(rawValue)) {
3483
+ continue;
3484
+ }
3485
+ if (typeof rawValue.schema === "string" && rawValue.schema.trim().length > 0) {
3486
+ return true;
3487
+ }
3488
+ if (selectShapeUsesRelationSchema(rawValue.select)) {
3489
+ return true;
3490
+ }
3491
+ }
3492
+ return false;
3493
+ }
3224
3494
  function compileColumnWhere(column, input) {
3225
3495
  const normalizedColumn = normalizeIdentifier(column, "where column");
3226
3496
  if (!isRecord5(input)) {
@@ -3357,6 +3627,258 @@ function compileOrderBy(orderBy) {
3357
3627
  };
3358
3628
  }
3359
3629
 
3630
+ // src/gateway/structured-select.ts
3631
+ var IDENTIFIER_SEGMENT_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
3632
+ function isIdentifierPath(value) {
3633
+ const segments = value.split(".").map((segment) => segment.trim());
3634
+ return segments.length > 1 && segments.every((segment) => IDENTIFIER_SEGMENT_PATTERN.test(segment));
3635
+ }
3636
+ function extractRelationHead(raw) {
3637
+ const trimmed = raw.trim();
3638
+ if (!trimmed) return "";
3639
+ const aliasIndex = trimmed.indexOf(":");
3640
+ const withoutAlias = aliasIndex >= 0 ? trimmed.slice(aliasIndex + 1).trim() : trimmed;
3641
+ const modifierIndex = withoutAlias.indexOf("!");
3642
+ return (modifierIndex >= 0 ? withoutAlias.slice(0, modifierIndex) : withoutAlias).trim();
3643
+ }
3644
+ function hasSchemaQualifiedRelationToken(select) {
3645
+ let singleQuoted = false;
3646
+ let doubleQuoted = false;
3647
+ let tokenStart = 0;
3648
+ for (let index = 0; index < select.length; index += 1) {
3649
+ const char = select[index];
3650
+ const next = index + 1 < select.length ? select[index + 1] : "";
3651
+ if (singleQuoted) {
3652
+ if (char === "'" && next === "'") {
3653
+ index += 1;
3654
+ continue;
3655
+ }
3656
+ if (char === "'") {
3657
+ singleQuoted = false;
3658
+ }
3659
+ continue;
3660
+ }
3661
+ if (doubleQuoted) {
3662
+ if (char === '"' && next === '"') {
3663
+ index += 1;
3664
+ continue;
3665
+ }
3666
+ if (char === '"') {
3667
+ doubleQuoted = false;
3668
+ }
3669
+ continue;
3670
+ }
3671
+ if (char === "'") {
3672
+ singleQuoted = true;
3673
+ continue;
3674
+ }
3675
+ if (char === '"') {
3676
+ doubleQuoted = true;
3677
+ continue;
3678
+ }
3679
+ if (char === "(") {
3680
+ const relationHead = extractRelationHead(select.slice(tokenStart, index));
3681
+ if (isIdentifierPath(relationHead)) {
3682
+ return true;
3683
+ }
3684
+ tokenStart = index + 1;
3685
+ continue;
3686
+ }
3687
+ if (char === "," || char === ")") {
3688
+ tokenStart = index + 1;
3689
+ }
3690
+ }
3691
+ return false;
3692
+ }
3693
+ function toStructuredSelectString(columns) {
3694
+ return Array.isArray(columns) ? columns.join(",") : columns;
3695
+ }
3696
+ function buildStructuredWhere(conditions) {
3697
+ if (!conditions?.length) return void 0;
3698
+ const where = {};
3699
+ for (const condition of conditions) {
3700
+ if (!condition.column) {
3701
+ return null;
3702
+ }
3703
+ if (condition.column_cast !== void 0 || condition.value_cast !== void 0) {
3704
+ return null;
3705
+ }
3706
+ const operand = condition.value;
3707
+ const operator = condition.operator;
3708
+ if (operator === "eq") {
3709
+ if (operand === void 0) return null;
3710
+ } else if (operator === "neq" || operator === "gt" || operator === "lt") {
3711
+ if (operand === void 0) return null;
3712
+ } else if (operator === "in") {
3713
+ if (!Array.isArray(operand)) return null;
3714
+ } else {
3715
+ return null;
3716
+ }
3717
+ const existing = where[condition.column];
3718
+ if (existing !== void 0 && (typeof existing !== "object" || existing === null || Array.isArray(existing))) {
3719
+ return null;
3720
+ }
3721
+ const next = existing ?? {};
3722
+ if (Object.prototype.hasOwnProperty.call(next, operator)) {
3723
+ return null;
3724
+ }
3725
+ next[operator] = operand;
3726
+ where[condition.column] = next;
3727
+ }
3728
+ return where;
3729
+ }
3730
+ function buildStructuredOrderBy(order) {
3731
+ if (!order?.field) return void 0;
3732
+ return {
3733
+ [order.field]: order.direction === "descending" ? "desc" : "asc"
3734
+ };
3735
+ }
3736
+ function buildStructuredSelectTransport(input) {
3737
+ const select = toStructuredSelectString(input.columns).trim();
3738
+ if (!select || select === "*") {
3739
+ return null;
3740
+ }
3741
+ if (!hasSchemaQualifiedRelationToken(select)) {
3742
+ return null;
3743
+ }
3744
+ if (input.count !== void 0 || input.head !== void 0) {
3745
+ return {
3746
+ error: "Schema-qualified nested select strings require structured select transport, which does not support count/head options in athena-js yet."
3747
+ };
3748
+ }
3749
+ const where = buildStructuredWhere(input.conditions);
3750
+ if (where === null) {
3751
+ return {
3752
+ error: "Schema-qualified nested select strings only support eq, neq, gt, lt, and in filters in athena-js structured select transport."
3753
+ };
3754
+ }
3755
+ return {
3756
+ select,
3757
+ payload: {
3758
+ table_name: input.tableName,
3759
+ select,
3760
+ where,
3761
+ orderBy: buildStructuredOrderBy(input.order),
3762
+ limit: input.limit,
3763
+ offset: input.offset,
3764
+ strip_nulls: input.stripNulls
3765
+ }
3766
+ };
3767
+ }
3768
+
3769
+ // src/query-transport.ts
3770
+ function canUseFindManyAstTransport(state) {
3771
+ return state.conditions.length === 0 && state.offset === void 0 && state.currentPage === void 0 && state.pageSize === void 0 && state.totalPages === void 0;
3772
+ }
3773
+ function toFindManyAstOrder(order) {
3774
+ if (!order) {
3775
+ return void 0;
3776
+ }
3777
+ return {
3778
+ column: order.field,
3779
+ ascending: order.direction !== "descending"
3780
+ };
3781
+ }
3782
+ function resolvePagination(input) {
3783
+ let limit = input.limit;
3784
+ let offset = input.offset;
3785
+ if (limit === void 0 && input.pageSize !== void 0) {
3786
+ limit = Math.max(0, Math.trunc(input.pageSize));
3787
+ }
3788
+ if (offset === void 0 && input.pageSize !== void 0 && input.currentPage !== void 0 && input.currentPage > 0) {
3789
+ offset = (Math.trunc(input.currentPage) - 1) * Math.max(0, Math.trunc(input.pageSize));
3790
+ }
3791
+ return { limit, offset };
3792
+ }
3793
+ function hasTypedEqualityComparison(conditions) {
3794
+ return conditions?.some(
3795
+ (condition) => condition.operator === "eq" && (condition.value_cast !== void 0 || condition.column_cast !== void 0)
3796
+ ) ?? false;
3797
+ }
3798
+ function createSelectTransportPlan(input) {
3799
+ const conditions = input.state.conditions.length ? input.state.conditions.map((condition) => ({ ...condition })) : void 0;
3800
+ if (hasTypedEqualityComparison(conditions) && !input.options?.head && !input.options?.count && conditions) {
3801
+ const query = input.buildTypedSelectQuery({
3802
+ tableName: input.tableName,
3803
+ columns: input.columns,
3804
+ conditions,
3805
+ limit: input.state.limit,
3806
+ offset: input.state.offset,
3807
+ currentPage: input.state.currentPage,
3808
+ pageSize: input.state.pageSize,
3809
+ order: input.state.order
3810
+ });
3811
+ if (query) {
3812
+ return {
3813
+ kind: "query",
3814
+ query,
3815
+ payload: { query }
3816
+ };
3817
+ }
3818
+ }
3819
+ const pagination = resolvePagination({
3820
+ limit: input.state.limit,
3821
+ offset: input.state.offset,
3822
+ currentPage: input.state.currentPage,
3823
+ pageSize: input.state.pageSize
3824
+ });
3825
+ const stripNulls = input.options?.stripNulls ?? true;
3826
+ const structuredSelectTransport = buildStructuredSelectTransport({
3827
+ tableName: input.tableName,
3828
+ columns: input.columns,
3829
+ conditions,
3830
+ limit: pagination.limit,
3831
+ offset: pagination.offset,
3832
+ order: input.state.order,
3833
+ stripNulls,
3834
+ count: input.options?.count,
3835
+ head: input.options?.head
3836
+ });
3837
+ if (structuredSelectTransport && "error" in structuredSelectTransport) {
3838
+ throw new Error(structuredSelectTransport.error);
3839
+ }
3840
+ if (structuredSelectTransport) {
3841
+ const { payload, select } = structuredSelectTransport;
3842
+ return {
3843
+ kind: "fetch",
3844
+ payload,
3845
+ debug: {
3846
+ columns: select,
3847
+ conditions,
3848
+ limit: pagination.limit,
3849
+ offset: pagination.offset,
3850
+ order: input.state.order
3851
+ }
3852
+ };
3853
+ }
3854
+ return {
3855
+ kind: "fetch",
3856
+ payload: {
3857
+ table_name: input.tableName,
3858
+ columns: input.columns,
3859
+ conditions,
3860
+ limit: input.state.limit,
3861
+ offset: input.state.offset,
3862
+ current_page: input.state.currentPage,
3863
+ page_size: input.state.pageSize,
3864
+ total_pages: input.state.totalPages,
3865
+ sort_by: input.state.order,
3866
+ strip_nulls: stripNulls,
3867
+ count: input.options?.count,
3868
+ head: input.options?.head
3869
+ },
3870
+ debug: {
3871
+ columns: input.columns,
3872
+ conditions,
3873
+ limit: input.state.limit,
3874
+ offset: input.state.offset,
3875
+ currentPage: input.state.currentPage,
3876
+ pageSize: input.state.pageSize,
3877
+ order: input.state.order
3878
+ }
3879
+ };
3880
+ }
3881
+
3360
3882
  // src/client.ts
3361
3883
  var DEFAULT_COLUMNS = "*";
3362
3884
  var SAFE_CAST_PATTERN = /^[a-z_][a-z0-9_]*(?:\[\])?$/i;
@@ -3371,18 +3893,6 @@ var QUERY_TRACE_STACK_SKIP_PATTERNS = [
3371
3893
  "node:internal",
3372
3894
  "internal/process"
3373
3895
  ];
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
3896
  function formatResult(response) {
3387
3897
  const result = {
3388
3898
  data: response.data ?? null,
@@ -3928,17 +4438,6 @@ function conditionToDebugSqlClause(condition) {
3928
4438
  return `TRUE /* unsupported condition: ${rawCondition} */`;
3929
4439
  }
3930
4440
  }
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
4441
  function appendOrderLimitOffset(sqlParts, order, limit, offset) {
3943
4442
  if (order?.field) {
3944
4443
  const direction = order.direction === "descending" ? "DESC" : "ASC";
@@ -4442,64 +4941,34 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
4442
4941
  );
4443
4942
  const runSelect = async (columns = DEFAULT_COLUMNS, options, executionState = snapshotState(), callsite) => {
4444
4943
  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(
4463
- tracer,
4464
- {
4465
- operation: "select",
4466
- endpoint: "/gateway/query",
4467
- table: resolvedTableName,
4468
- sql: query,
4469
- payload: payload2,
4470
- options
4471
- },
4472
- async () => {
4473
- const queryResponse = await client.queryGateway(payload2, options);
4474
- return formatGatewayResult(queryResponse, { table: resolvedTableName, operation: "select" });
4475
- },
4476
- callsite
4477
- );
4478
- }
4479
- }
4480
- const payload = {
4481
- table_name: resolvedTableName,
4944
+ const plan = createSelectTransportPlan({
4945
+ tableName: resolvedTableName,
4482
4946
  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
- };
4947
+ state: executionState,
4948
+ options,
4949
+ buildTypedSelectQuery
4950
+ });
4951
+ if (plan.kind === "query") {
4952
+ return executeWithQueryTrace(
4953
+ tracer,
4954
+ {
4955
+ operation: "select",
4956
+ endpoint: "/gateway/query",
4957
+ table: resolvedTableName,
4958
+ sql: plan.query,
4959
+ payload: plan.payload,
4960
+ options
4961
+ },
4962
+ async () => {
4963
+ const queryResponse = await client.queryGateway(plan.payload, options);
4964
+ return formatGatewayResult(queryResponse, { table: resolvedTableName, operation: "select" });
4965
+ },
4966
+ callsite
4967
+ );
4968
+ }
4494
4969
  const sql = buildDebugSelectQuery({
4495
4970
  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
4971
+ ...plan.debug
4503
4972
  });
4504
4973
  return executeWithQueryTrace(
4505
4974
  tracer,
@@ -4508,11 +4977,11 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
4508
4977
  endpoint: "/gateway/fetch",
4509
4978
  table: resolvedTableName,
4510
4979
  sql,
4511
- payload,
4980
+ payload: plan.payload,
4512
4981
  options
4513
4982
  },
4514
4983
  async () => {
4515
- const response = await client.fetchGateway(payload, options);
4984
+ const response = await client.fetchGateway(plan.payload, options);
4516
4985
  return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
4517
4986
  },
4518
4987
  callsite
@@ -4585,7 +5054,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
4585
5054
  if (options.limit !== void 0) {
4586
5055
  executionState.limit = options.limit;
4587
5056
  }
4588
- if (experimental?.findManyAst && canUseFindManyAstTransport(baseState)) {
5057
+ if (experimental?.findManyAst && canUseFindManyAstTransport(baseState) && !selectShapeUsesRelationSchema(options.select)) {
4589
5058
  const resolvedTableName = resolveTableNameForCall(tableName, void 0);
4590
5059
  const payload = {
4591
5060
  table_name: resolvedTableName,
@@ -4907,7 +5376,13 @@ function createClientFromConfig(config) {
4907
5376
  const formatGatewayResult = createResultFormatter();
4908
5377
  const queryTracer = createQueryTracer(config.experimental);
4909
5378
  const auth = createAuthClient(config.auth);
4910
- const from = (table) => createTableBuilder(table, gateway, formatGatewayResult, queryTracer, config.experimental);
5379
+ const from = (table, options) => createTableBuilder(
5380
+ resolveTableNameForCall(table, options?.schema),
5381
+ gateway,
5382
+ formatGatewayResult,
5383
+ queryTracer,
5384
+ config.experimental
5385
+ );
4911
5386
  const rpc = (fn, args, options) => {
4912
5387
  const normalizedFn = fn.trim();
4913
5388
  if (!normalizedFn) {
@@ -4930,6 +5405,7 @@ function createClientFromConfig(config) {
4930
5405
  db,
4931
5406
  rpc,
4932
5407
  query,
5408
+ verifyConnection: gateway.verifyConnection,
4933
5409
  auth: auth.auth
4934
5410
  };
4935
5411
  }