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