@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/browser.cjs CHANGED
@@ -60,8 +60,74 @@ function isAthenaGatewayError(error) {
60
60
  return error instanceof AthenaGatewayError;
61
61
  }
62
62
 
63
+ // src/gateway/url.ts
64
+ var ATHENA_DEFAULT_BASE_URL = "https://athena-db.com";
65
+ function describeReceivedValue(value) {
66
+ if (value === void 0) return "undefined";
67
+ if (value === null) return "null";
68
+ if (typeof value === "string") {
69
+ return value.trim().length > 0 ? JSON.stringify(value) : "an empty string";
70
+ }
71
+ return `${typeof value} ${JSON.stringify(value)}`;
72
+ }
73
+ function invalidBaseUrlError(message, hint) {
74
+ return new AthenaGatewayError({
75
+ code: "INVALID_URL",
76
+ message,
77
+ status: 0,
78
+ hint
79
+ });
80
+ }
81
+ function normalizeAthenaGatewayBaseUrl(input, options = {}) {
82
+ const label = options.label ?? "Athena gateway base URL";
83
+ const candidate = input ?? options.defaultBaseUrl;
84
+ if (candidate === void 0 || candidate === null) {
85
+ throw invalidBaseUrlError(
86
+ `${label} must be a non-empty absolute http(s) URL. Received ${describeReceivedValue(input)}.`,
87
+ 'Set ATHENA_URL (or pass createClient(url, ...)) to a full URL such as "https://mirror3.athena-db.com".'
88
+ );
89
+ }
90
+ const trimmed = candidate.trim();
91
+ if (!trimmed) {
92
+ throw invalidBaseUrlError(
93
+ `${label} must be a non-empty absolute http(s) URL. Received ${describeReceivedValue(candidate)}.`,
94
+ 'Set ATHENA_URL (or pass createClient(url, ...)) to a full URL such as "https://mirror3.athena-db.com".'
95
+ );
96
+ }
97
+ let parsed;
98
+ try {
99
+ parsed = new URL(trimmed);
100
+ } catch {
101
+ throw invalidBaseUrlError(
102
+ `${label} must be a valid absolute http(s) URL. Received ${describeReceivedValue(candidate)}.`,
103
+ 'Use a full URL including the protocol, for example "https://mirror3.athena-db.com".'
104
+ );
105
+ }
106
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
107
+ throw invalidBaseUrlError(
108
+ `${label} must use http or https. Received ${JSON.stringify(trimmed)}.`,
109
+ 'Use an Athena gateway URL such as "https://mirror3.athena-db.com".'
110
+ );
111
+ }
112
+ if (parsed.search || parsed.hash) {
113
+ throw invalidBaseUrlError(
114
+ `${label} must not include query parameters or hash fragments. Received ${JSON.stringify(trimmed)}.`,
115
+ 'Pass only the base URL. Endpoint paths such as "/gateway/fetch" are appended by the SDK.'
116
+ );
117
+ }
118
+ return parsed.toString().replace(/\/+$/, "");
119
+ }
120
+ function buildAthenaGatewayUrl(baseUrl, path) {
121
+ if (!path.startsWith("/")) {
122
+ throw invalidBaseUrlError(
123
+ `Athena gateway path must start with "/". Received ${JSON.stringify(path)}.`,
124
+ 'Use a leading slash such as "/gateway/fetch" or "/".'
125
+ );
126
+ }
127
+ return `${baseUrl}${path}`;
128
+ }
129
+
63
130
  // src/gateway/client.ts
64
- var DEFAULT_BASE_URL = "https://athena-db.com";
65
131
  var DEFAULT_CLIENT = "railway_direct";
66
132
  var FALLBACK_SDK_VERSION = "1.3.0";
67
133
  var SDK_NAME = "xylex-group/athena";
@@ -258,9 +324,172 @@ function buildHeaders(config, options) {
258
324
  });
259
325
  return headers;
260
326
  }
327
+ function toInvalidUrlResponse(error, endpoint, method) {
328
+ const message = error instanceof Error ? error.message : String(error);
329
+ const gatewayError = error instanceof AthenaGatewayError ? error : new AthenaGatewayError({
330
+ code: "INVALID_URL",
331
+ message,
332
+ status: 0,
333
+ endpoint,
334
+ method,
335
+ cause: message,
336
+ hint: "Set ATHENA_URL to a full http(s) URL before running queries."
337
+ });
338
+ return {
339
+ ok: false,
340
+ status: 0,
341
+ statusText: null,
342
+ data: null,
343
+ error: gatewayError.message,
344
+ errorDetails: detailsFromError(
345
+ new AthenaGatewayError({
346
+ code: gatewayError.code,
347
+ message: gatewayError.message,
348
+ status: gatewayError.status,
349
+ endpoint,
350
+ method,
351
+ requestId: gatewayError.requestId,
352
+ hint: gatewayError.hint,
353
+ cause: gatewayError.causeDetail
354
+ })
355
+ ),
356
+ raw: null
357
+ };
358
+ }
359
+ function resolveGatewayBaseUrl(input) {
360
+ return normalizeAthenaGatewayBaseUrl(input, {
361
+ defaultBaseUrl: ATHENA_DEFAULT_BASE_URL
362
+ });
363
+ }
364
+ function resolveProbePath(path) {
365
+ if (!path) return "/";
366
+ if (!path.startsWith("/")) {
367
+ throw new AthenaGatewayError({
368
+ code: "INVALID_URL",
369
+ message: `Athena gateway probe path must start with "/". Received ${JSON.stringify(path)}.`,
370
+ status: 0,
371
+ hint: 'Use a leading slash such as "/" or "/health".'
372
+ });
373
+ }
374
+ return path;
375
+ }
376
+ function mergeConnectionHeaders(baseHeaders, headers) {
377
+ const merged = {
378
+ ...baseHeaders,
379
+ ...headers ?? {}
380
+ };
381
+ if (!merged["X-Athena-Sdk"] && !merged["x-athena-sdk"]) {
382
+ merged["X-Athena-Sdk"] = SDK_HEADER_VALUE;
383
+ }
384
+ return merged;
385
+ }
386
+ async function performConnectionCheck(baseUrl, requestHeaders, options) {
387
+ const path = resolveProbePath(options?.path);
388
+ const url = buildAthenaGatewayUrl(baseUrl, path);
389
+ try {
390
+ const response = await fetch(url, {
391
+ method: "GET",
392
+ headers: mergeConnectionHeaders(requestHeaders, options?.headers),
393
+ signal: options?.signal
394
+ });
395
+ const rawText = await response.text();
396
+ const requestId = resolveRequestId(response.headers);
397
+ const parsedBody = parseResponseBody(
398
+ rawText ?? "",
399
+ response.headers.get("content-type")
400
+ );
401
+ if (parsedBody.parseFailed) {
402
+ const invalidJsonError = new AthenaGatewayError({
403
+ code: "INVALID_JSON",
404
+ message: "Gateway probe returned malformed JSON",
405
+ status: response.status,
406
+ method: "GET",
407
+ requestId,
408
+ hint: "Verify the gateway response body is valid JSON.",
409
+ cause: rawText.slice(0, 300)
410
+ });
411
+ return {
412
+ ok: false,
413
+ reachable: true,
414
+ status: response.status,
415
+ statusText: resolveStatusText(response, parsedBody.parsed),
416
+ baseUrl,
417
+ url,
418
+ error: invalidJsonError.message,
419
+ errorDetails: detailsFromError(invalidJsonError),
420
+ raw: parsedBody.parsed
421
+ };
422
+ }
423
+ const parsed = parsedBody.parsed;
424
+ if (!response.ok) {
425
+ const httpError = new AthenaGatewayError({
426
+ code: "HTTP_ERROR",
427
+ message: resolveErrorMessage(
428
+ parsed,
429
+ `Athena gateway GET ${path} failed with status ${response.status}`
430
+ ),
431
+ status: response.status,
432
+ method: "GET",
433
+ requestId,
434
+ hint: resolveErrorHint(parsed)
435
+ });
436
+ return {
437
+ ok: false,
438
+ reachable: true,
439
+ status: response.status,
440
+ statusText: resolveStatusText(response, parsed),
441
+ baseUrl,
442
+ url,
443
+ error: httpError.message,
444
+ errorDetails: detailsFromError(httpError),
445
+ raw: parsed
446
+ };
447
+ }
448
+ return {
449
+ ok: true,
450
+ reachable: true,
451
+ status: response.status,
452
+ statusText: resolveStatusText(response, parsed),
453
+ baseUrl,
454
+ url,
455
+ error: void 0,
456
+ errorDetails: null,
457
+ raw: parsed
458
+ };
459
+ } catch (callError) {
460
+ const message = callError instanceof Error ? callError.message : String(callError);
461
+ const networkError = new AthenaGatewayError({
462
+ code: "NETWORK_ERROR",
463
+ message: `Network error while probing Athena gateway ${url}: ${message}`,
464
+ method: "GET",
465
+ cause: message,
466
+ hint: "Check gateway URL, DNS, and network reachability."
467
+ });
468
+ return {
469
+ ok: false,
470
+ reachable: false,
471
+ status: 0,
472
+ statusText: null,
473
+ baseUrl,
474
+ url,
475
+ error: networkError.message,
476
+ errorDetails: detailsFromError(networkError),
477
+ raw: null
478
+ };
479
+ }
480
+ }
481
+ async function verifyAthenaGatewayUrl(baseUrl, options) {
482
+ const normalizedBaseUrl = normalizeAthenaGatewayBaseUrl(baseUrl);
483
+ return performConnectionCheck(normalizedBaseUrl, { "X-Athena-Sdk": SDK_HEADER_VALUE }, options);
484
+ }
261
485
  async function callAthena(config, endpoint, method, payload, options) {
262
- const baseUrl = (options?.baseUrl ?? config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
263
- const url = `${baseUrl}${endpoint}`;
486
+ let baseUrl;
487
+ try {
488
+ baseUrl = resolveGatewayBaseUrl(options?.baseUrl ?? config.baseUrl);
489
+ } catch (error) {
490
+ return toInvalidUrlResponse(error, endpoint, method);
491
+ }
492
+ const url = buildAthenaGatewayUrl(baseUrl, endpoint);
264
493
  const headers = buildHeaders(config, options);
265
494
  try {
266
495
  const requestInit = {
@@ -357,32 +586,44 @@ async function callAthena(config, endpoint, method, payload, options) {
357
586
  }
358
587
  }
359
588
  function createAthenaGatewayClient(config = {}) {
589
+ const normalizedBaseUrl = resolveGatewayBaseUrl(config.baseUrl);
590
+ const normalizedConfig = {
591
+ ...config,
592
+ baseUrl: normalizedBaseUrl
593
+ };
360
594
  return {
361
- baseUrl: (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, ""),
595
+ baseUrl: normalizedBaseUrl,
362
596
  buildHeaders(options) {
363
- return buildHeaders(config, options);
597
+ return buildHeaders(normalizedConfig, options);
598
+ },
599
+ verifyConnection(options) {
600
+ return performConnectionCheck(
601
+ normalizedBaseUrl,
602
+ buildHeaders(normalizedConfig),
603
+ options
604
+ );
364
605
  },
365
606
  fetchGateway(payload, options) {
366
- return callAthena(config, "/gateway/fetch", "POST", payload, options);
607
+ return callAthena(normalizedConfig, "/gateway/fetch", "POST", payload, options);
367
608
  },
368
609
  insertGateway(payload, options) {
369
- return callAthena(config, "/gateway/insert", "PUT", payload, options);
610
+ return callAthena(normalizedConfig, "/gateway/insert", "PUT", payload, options);
370
611
  },
371
612
  updateGateway(payload, options) {
372
- return callAthena(config, "/gateway/update", "POST", payload, options);
613
+ return callAthena(normalizedConfig, "/gateway/update", "POST", payload, options);
373
614
  },
374
615
  deleteGateway(payload, options) {
375
- return callAthena(config, "/gateway/delete", "DELETE", payload, options);
616
+ return callAthena(normalizedConfig, "/gateway/delete", "DELETE", payload, options);
376
617
  },
377
618
  rpcGateway(payload, options) {
378
619
  if (options?.get) {
379
620
  const endpoint = buildRpcGetEndpoint(payload);
380
- return callAthena(config, endpoint, "GET", null, options);
621
+ return callAthena(normalizedConfig, endpoint, "GET", null, options);
381
622
  }
382
- return callAthena(config, "/gateway/rpc", "POST", payload, options);
623
+ return callAthena(normalizedConfig, "/gateway/rpc", "POST", payload, options);
383
624
  },
384
625
  queryGateway(payload, options) {
385
- return callAthena(config, "/gateway/query", "POST", payload, options);
626
+ return callAthena(normalizedConfig, "/gateway/query", "POST", payload, options);
386
627
  }
387
628
  };
388
629
  }
@@ -2024,6 +2265,7 @@ function classifyKind(status, code, message) {
2024
2265
  if (status === 404 || hasNotFoundPattern) return "not_found";
2025
2266
  if (status === 401 || status === 403 || hasAuthPattern) return "auth";
2026
2267
  if (status === 429 || hasRateLimitPattern) return "rate_limit";
2268
+ if (code === "INVALID_URL") return "validation";
2027
2269
  if (status === 400 || status === 422 || hasValidationPattern) return "validation";
2028
2270
  if (code === "NETWORK_ERROR" || status === 0 || status !== void 0 && status >= 500 || hasTransientPattern) {
2029
2271
  return "transient";
@@ -2031,6 +2273,9 @@ function classifyKind(status, code, message) {
2031
2273
  return "unknown";
2032
2274
  }
2033
2275
  function toAthenaErrorCode(kind, status, gatewayCode) {
2276
+ if (gatewayCode === "INVALID_URL") {
2277
+ return AthenaErrorCode.ValidationFailed;
2278
+ }
2034
2279
  if (gatewayCode === "NETWORK_ERROR" || kind === "transient" && status === 0) {
2035
2280
  return AthenaErrorCode.NetworkUnavailable;
2036
2281
  }
@@ -2379,8 +2624,8 @@ async function withRetry(config, fn) {
2379
2624
  // src/db/module.ts
2380
2625
  function createDbModule(input) {
2381
2626
  const db = {
2382
- from(table) {
2383
- return input.from(table);
2627
+ from(table, options) {
2628
+ return input.from(table, options);
2384
2629
  },
2385
2630
  select(table, columns, options) {
2386
2631
  return input.from(table).select(columns, options);
@@ -2485,7 +2730,19 @@ function buildGatewayCondition(operator, column, value) {
2485
2730
  function compileRelationToken(key, node) {
2486
2731
  const nested = compileSelectShape(node.select);
2487
2732
  const propertyKey = normalizeIdentifier(key, "select relation key");
2488
- const relationToken = normalizeIdentifier(node.via ?? propertyKey, "select relation token");
2733
+ if (node.schema && node.via) {
2734
+ throw new Error(
2735
+ `findMany relation "${propertyKey}" cannot combine schema and via yet; use schema with the relation key, or use via without schema`
2736
+ );
2737
+ }
2738
+ const relationTokenBase = normalizeIdentifier(node.via ?? propertyKey, "select relation token");
2739
+ if (node.schema && relationTokenBase.includes(".")) {
2740
+ throw new Error(
2741
+ `findMany relation "${propertyKey}" already resolves to a qualified relation token; do not also set schema`
2742
+ );
2743
+ }
2744
+ const relationSchema = node.schema?.trim();
2745
+ const relationToken = relationSchema ? `${normalizeIdentifier(relationSchema, "select relation schema")}.${relationTokenBase}` : relationTokenBase;
2489
2746
  const alias = node.as?.trim() || (relationToken !== propertyKey ? propertyKey : "");
2490
2747
  const prefix = alias ? `${alias}:` : "";
2491
2748
  return `${prefix}${relationToken}(${nested})`;
@@ -2514,6 +2771,23 @@ function compileSelectShape(select) {
2514
2771
  }
2515
2772
  return tokens.join(",");
2516
2773
  }
2774
+ function selectShapeUsesRelationSchema(select) {
2775
+ if (!isRecord5(select)) {
2776
+ return false;
2777
+ }
2778
+ for (const rawValue of Object.values(select)) {
2779
+ if (!isRelationSelectNode(rawValue)) {
2780
+ continue;
2781
+ }
2782
+ if (typeof rawValue.schema === "string" && rawValue.schema.trim().length > 0) {
2783
+ return true;
2784
+ }
2785
+ if (selectShapeUsesRelationSchema(rawValue.select)) {
2786
+ return true;
2787
+ }
2788
+ }
2789
+ return false;
2790
+ }
2517
2791
  function compileColumnWhere(column, input) {
2518
2792
  const normalizedColumn = normalizeIdentifier(column, "where column");
2519
2793
  if (!isRecord5(input)) {
@@ -2650,6 +2924,258 @@ function compileOrderBy(orderBy) {
2650
2924
  };
2651
2925
  }
2652
2926
 
2927
+ // src/gateway/structured-select.ts
2928
+ var IDENTIFIER_SEGMENT_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
2929
+ function isIdentifierPath(value) {
2930
+ const segments = value.split(".").map((segment) => segment.trim());
2931
+ return segments.length > 1 && segments.every((segment) => IDENTIFIER_SEGMENT_PATTERN.test(segment));
2932
+ }
2933
+ function extractRelationHead(raw) {
2934
+ const trimmed = raw.trim();
2935
+ if (!trimmed) return "";
2936
+ const aliasIndex = trimmed.indexOf(":");
2937
+ const withoutAlias = aliasIndex >= 0 ? trimmed.slice(aliasIndex + 1).trim() : trimmed;
2938
+ const modifierIndex = withoutAlias.indexOf("!");
2939
+ return (modifierIndex >= 0 ? withoutAlias.slice(0, modifierIndex) : withoutAlias).trim();
2940
+ }
2941
+ function hasSchemaQualifiedRelationToken(select) {
2942
+ let singleQuoted = false;
2943
+ let doubleQuoted = false;
2944
+ let tokenStart = 0;
2945
+ for (let index = 0; index < select.length; index += 1) {
2946
+ const char = select[index];
2947
+ const next = index + 1 < select.length ? select[index + 1] : "";
2948
+ if (singleQuoted) {
2949
+ if (char === "'" && next === "'") {
2950
+ index += 1;
2951
+ continue;
2952
+ }
2953
+ if (char === "'") {
2954
+ singleQuoted = false;
2955
+ }
2956
+ continue;
2957
+ }
2958
+ if (doubleQuoted) {
2959
+ if (char === '"' && next === '"') {
2960
+ index += 1;
2961
+ continue;
2962
+ }
2963
+ if (char === '"') {
2964
+ doubleQuoted = false;
2965
+ }
2966
+ continue;
2967
+ }
2968
+ if (char === "'") {
2969
+ singleQuoted = true;
2970
+ continue;
2971
+ }
2972
+ if (char === '"') {
2973
+ doubleQuoted = true;
2974
+ continue;
2975
+ }
2976
+ if (char === "(") {
2977
+ const relationHead = extractRelationHead(select.slice(tokenStart, index));
2978
+ if (isIdentifierPath(relationHead)) {
2979
+ return true;
2980
+ }
2981
+ tokenStart = index + 1;
2982
+ continue;
2983
+ }
2984
+ if (char === "," || char === ")") {
2985
+ tokenStart = index + 1;
2986
+ }
2987
+ }
2988
+ return false;
2989
+ }
2990
+ function toStructuredSelectString(columns) {
2991
+ return Array.isArray(columns) ? columns.join(",") : columns;
2992
+ }
2993
+ function buildStructuredWhere(conditions) {
2994
+ if (!conditions?.length) return void 0;
2995
+ const where = {};
2996
+ for (const condition of conditions) {
2997
+ if (!condition.column) {
2998
+ return null;
2999
+ }
3000
+ if (condition.column_cast !== void 0 || condition.value_cast !== void 0) {
3001
+ return null;
3002
+ }
3003
+ const operand = condition.value;
3004
+ const operator = condition.operator;
3005
+ if (operator === "eq") {
3006
+ if (operand === void 0) return null;
3007
+ } else if (operator === "neq" || operator === "gt" || operator === "lt") {
3008
+ if (operand === void 0) return null;
3009
+ } else if (operator === "in") {
3010
+ if (!Array.isArray(operand)) return null;
3011
+ } else {
3012
+ return null;
3013
+ }
3014
+ const existing = where[condition.column];
3015
+ if (existing !== void 0 && (typeof existing !== "object" || existing === null || Array.isArray(existing))) {
3016
+ return null;
3017
+ }
3018
+ const next = existing ?? {};
3019
+ if (Object.prototype.hasOwnProperty.call(next, operator)) {
3020
+ return null;
3021
+ }
3022
+ next[operator] = operand;
3023
+ where[condition.column] = next;
3024
+ }
3025
+ return where;
3026
+ }
3027
+ function buildStructuredOrderBy(order) {
3028
+ if (!order?.field) return void 0;
3029
+ return {
3030
+ [order.field]: order.direction === "descending" ? "desc" : "asc"
3031
+ };
3032
+ }
3033
+ function buildStructuredSelectTransport(input) {
3034
+ const select = toStructuredSelectString(input.columns).trim();
3035
+ if (!select || select === "*") {
3036
+ return null;
3037
+ }
3038
+ if (!hasSchemaQualifiedRelationToken(select)) {
3039
+ return null;
3040
+ }
3041
+ if (input.count !== void 0 || input.head !== void 0) {
3042
+ return {
3043
+ error: "Schema-qualified nested select strings require structured select transport, which does not support count/head options in athena-js yet."
3044
+ };
3045
+ }
3046
+ const where = buildStructuredWhere(input.conditions);
3047
+ if (where === null) {
3048
+ return {
3049
+ error: "Schema-qualified nested select strings only support eq, neq, gt, lt, and in filters in athena-js structured select transport."
3050
+ };
3051
+ }
3052
+ return {
3053
+ select,
3054
+ payload: {
3055
+ table_name: input.tableName,
3056
+ select,
3057
+ where,
3058
+ orderBy: buildStructuredOrderBy(input.order),
3059
+ limit: input.limit,
3060
+ offset: input.offset,
3061
+ strip_nulls: input.stripNulls
3062
+ }
3063
+ };
3064
+ }
3065
+
3066
+ // src/query-transport.ts
3067
+ function canUseFindManyAstTransport(state) {
3068
+ return state.conditions.length === 0 && state.offset === void 0 && state.currentPage === void 0 && state.pageSize === void 0 && state.totalPages === void 0;
3069
+ }
3070
+ function toFindManyAstOrder(order) {
3071
+ if (!order) {
3072
+ return void 0;
3073
+ }
3074
+ return {
3075
+ column: order.field,
3076
+ ascending: order.direction !== "descending"
3077
+ };
3078
+ }
3079
+ function resolvePagination(input) {
3080
+ let limit = input.limit;
3081
+ let offset = input.offset;
3082
+ if (limit === void 0 && input.pageSize !== void 0) {
3083
+ limit = Math.max(0, Math.trunc(input.pageSize));
3084
+ }
3085
+ if (offset === void 0 && input.pageSize !== void 0 && input.currentPage !== void 0 && input.currentPage > 0) {
3086
+ offset = (Math.trunc(input.currentPage) - 1) * Math.max(0, Math.trunc(input.pageSize));
3087
+ }
3088
+ return { limit, offset };
3089
+ }
3090
+ function hasTypedEqualityComparison(conditions) {
3091
+ return conditions?.some(
3092
+ (condition) => condition.operator === "eq" && (condition.value_cast !== void 0 || condition.column_cast !== void 0)
3093
+ ) ?? false;
3094
+ }
3095
+ function createSelectTransportPlan(input) {
3096
+ const conditions = input.state.conditions.length ? input.state.conditions.map((condition) => ({ ...condition })) : void 0;
3097
+ if (hasTypedEqualityComparison(conditions) && !input.options?.head && !input.options?.count && conditions) {
3098
+ const query = input.buildTypedSelectQuery({
3099
+ tableName: input.tableName,
3100
+ columns: input.columns,
3101
+ conditions,
3102
+ limit: input.state.limit,
3103
+ offset: input.state.offset,
3104
+ currentPage: input.state.currentPage,
3105
+ pageSize: input.state.pageSize,
3106
+ order: input.state.order
3107
+ });
3108
+ if (query) {
3109
+ return {
3110
+ kind: "query",
3111
+ query,
3112
+ payload: { query }
3113
+ };
3114
+ }
3115
+ }
3116
+ const pagination = resolvePagination({
3117
+ limit: input.state.limit,
3118
+ offset: input.state.offset,
3119
+ currentPage: input.state.currentPage,
3120
+ pageSize: input.state.pageSize
3121
+ });
3122
+ const stripNulls = input.options?.stripNulls ?? true;
3123
+ const structuredSelectTransport = buildStructuredSelectTransport({
3124
+ tableName: input.tableName,
3125
+ columns: input.columns,
3126
+ conditions,
3127
+ limit: pagination.limit,
3128
+ offset: pagination.offset,
3129
+ order: input.state.order,
3130
+ stripNulls,
3131
+ count: input.options?.count,
3132
+ head: input.options?.head
3133
+ });
3134
+ if (structuredSelectTransport && "error" in structuredSelectTransport) {
3135
+ throw new Error(structuredSelectTransport.error);
3136
+ }
3137
+ if (structuredSelectTransport) {
3138
+ const { payload, select } = structuredSelectTransport;
3139
+ return {
3140
+ kind: "fetch",
3141
+ payload,
3142
+ debug: {
3143
+ columns: select,
3144
+ conditions,
3145
+ limit: pagination.limit,
3146
+ offset: pagination.offset,
3147
+ order: input.state.order
3148
+ }
3149
+ };
3150
+ }
3151
+ return {
3152
+ kind: "fetch",
3153
+ payload: {
3154
+ table_name: input.tableName,
3155
+ columns: input.columns,
3156
+ conditions,
3157
+ limit: input.state.limit,
3158
+ offset: input.state.offset,
3159
+ current_page: input.state.currentPage,
3160
+ page_size: input.state.pageSize,
3161
+ total_pages: input.state.totalPages,
3162
+ sort_by: input.state.order,
3163
+ strip_nulls: stripNulls,
3164
+ count: input.options?.count,
3165
+ head: input.options?.head
3166
+ },
3167
+ debug: {
3168
+ columns: input.columns,
3169
+ conditions,
3170
+ limit: input.state.limit,
3171
+ offset: input.state.offset,
3172
+ currentPage: input.state.currentPage,
3173
+ pageSize: input.state.pageSize,
3174
+ order: input.state.order
3175
+ }
3176
+ };
3177
+ }
3178
+
2653
3179
  // src/client.ts
2654
3180
  var DEFAULT_COLUMNS = "*";
2655
3181
  var SAFE_CAST_PATTERN = /^[a-z_][a-z0-9_]*(?:\[\])?$/i;
@@ -2664,18 +3190,6 @@ var QUERY_TRACE_STACK_SKIP_PATTERNS = [
2664
3190
  "node:internal",
2665
3191
  "internal/process"
2666
3192
  ];
2667
- function canUseFindManyAstTransport(state) {
2668
- return state.conditions.length === 0 && state.offset === void 0 && state.currentPage === void 0 && state.pageSize === void 0 && state.totalPages === void 0;
2669
- }
2670
- function toFindManyAstOrder(order) {
2671
- if (!order) {
2672
- return void 0;
2673
- }
2674
- return {
2675
- column: order.field,
2676
- ascending: order.direction !== "descending"
2677
- };
2678
- }
2679
3193
  function formatResult(response) {
2680
3194
  const result = {
2681
3195
  data: response.data ?? null,
@@ -3221,17 +3735,6 @@ function conditionToDebugSqlClause(condition) {
3221
3735
  return `TRUE /* unsupported condition: ${rawCondition} */`;
3222
3736
  }
3223
3737
  }
3224
- function resolvePagination(input) {
3225
- let limit = input.limit;
3226
- let offset = input.offset;
3227
- if (limit === void 0 && input.pageSize !== void 0) {
3228
- limit = input.pageSize;
3229
- }
3230
- if (offset === void 0 && input.pageSize !== void 0 && input.currentPage !== void 0 && input.currentPage > 0) {
3231
- offset = (input.currentPage - 1) * input.pageSize;
3232
- }
3233
- return { limit, offset };
3234
- }
3235
3738
  function appendOrderLimitOffset(sqlParts, order, limit, offset) {
3236
3739
  if (order?.field) {
3237
3740
  const direction = order.direction === "descending" ? "DESC" : "ASC";
@@ -3735,64 +4238,34 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
3735
4238
  );
3736
4239
  const runSelect = async (columns = DEFAULT_COLUMNS, options, executionState = snapshotState(), callsite) => {
3737
4240
  const resolvedTableName = resolveTableNameForCall(tableName, options?.schema);
3738
- const conditions = executionState.conditions.length ? executionState.conditions.map((condition) => ({ ...condition })) : void 0;
3739
- const hasTypedEqualityComparison = conditions?.some(
3740
- (condition) => condition.operator === "eq" && (condition.value_cast !== void 0 || condition.column_cast !== void 0)
3741
- ) ?? false;
3742
- if (hasTypedEqualityComparison && !options?.head && !options?.count && conditions) {
3743
- const query = buildTypedSelectQuery({
3744
- tableName: resolvedTableName,
3745
- columns,
3746
- conditions,
3747
- limit: executionState.limit,
3748
- offset: executionState.offset,
3749
- currentPage: executionState.currentPage,
3750
- pageSize: executionState.pageSize,
3751
- order: executionState.order
3752
- });
3753
- if (query) {
3754
- const payload2 = { query };
3755
- return executeWithQueryTrace(
3756
- tracer,
3757
- {
3758
- operation: "select",
3759
- endpoint: "/gateway/query",
3760
- table: resolvedTableName,
3761
- sql: query,
3762
- payload: payload2,
3763
- options
3764
- },
3765
- async () => {
3766
- const queryResponse = await client.queryGateway(payload2, options);
3767
- return formatGatewayResult(queryResponse, { table: resolvedTableName, operation: "select" });
3768
- },
3769
- callsite
3770
- );
3771
- }
3772
- }
3773
- const payload = {
3774
- table_name: resolvedTableName,
4241
+ const plan = createSelectTransportPlan({
4242
+ tableName: resolvedTableName,
3775
4243
  columns,
3776
- conditions,
3777
- limit: executionState.limit,
3778
- offset: executionState.offset,
3779
- current_page: executionState.currentPage,
3780
- page_size: executionState.pageSize,
3781
- total_pages: executionState.totalPages,
3782
- sort_by: executionState.order,
3783
- strip_nulls: options?.stripNulls ?? true,
3784
- count: options?.count,
3785
- head: options?.head
3786
- };
4244
+ state: executionState,
4245
+ options,
4246
+ buildTypedSelectQuery
4247
+ });
4248
+ if (plan.kind === "query") {
4249
+ return executeWithQueryTrace(
4250
+ tracer,
4251
+ {
4252
+ operation: "select",
4253
+ endpoint: "/gateway/query",
4254
+ table: resolvedTableName,
4255
+ sql: plan.query,
4256
+ payload: plan.payload,
4257
+ options
4258
+ },
4259
+ async () => {
4260
+ const queryResponse = await client.queryGateway(plan.payload, options);
4261
+ return formatGatewayResult(queryResponse, { table: resolvedTableName, operation: "select" });
4262
+ },
4263
+ callsite
4264
+ );
4265
+ }
3787
4266
  const sql = buildDebugSelectQuery({
3788
4267
  tableName: resolvedTableName,
3789
- columns,
3790
- conditions,
3791
- limit: executionState.limit,
3792
- offset: executionState.offset,
3793
- currentPage: executionState.currentPage,
3794
- pageSize: executionState.pageSize,
3795
- order: executionState.order
4268
+ ...plan.debug
3796
4269
  });
3797
4270
  return executeWithQueryTrace(
3798
4271
  tracer,
@@ -3801,11 +4274,11 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
3801
4274
  endpoint: "/gateway/fetch",
3802
4275
  table: resolvedTableName,
3803
4276
  sql,
3804
- payload,
4277
+ payload: plan.payload,
3805
4278
  options
3806
4279
  },
3807
4280
  async () => {
3808
- const response = await client.fetchGateway(payload, options);
4281
+ const response = await client.fetchGateway(plan.payload, options);
3809
4282
  return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
3810
4283
  },
3811
4284
  callsite
@@ -3878,7 +4351,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
3878
4351
  if (options.limit !== void 0) {
3879
4352
  executionState.limit = options.limit;
3880
4353
  }
3881
- if (experimental?.findManyAst && canUseFindManyAstTransport(baseState)) {
4354
+ if (experimental?.findManyAst && canUseFindManyAstTransport(baseState) && !selectShapeUsesRelationSchema(options.select)) {
3882
4355
  const resolvedTableName = resolveTableNameForCall(tableName, void 0);
3883
4356
  const payload = {
3884
4357
  table_name: resolvedTableName,
@@ -4200,7 +4673,13 @@ function createClientFromConfig(config) {
4200
4673
  const formatGatewayResult = createResultFormatter(config.experimental);
4201
4674
  const queryTracer = createQueryTracer(config.experimental);
4202
4675
  const auth = createAuthClient(config.auth);
4203
- const from = (table) => createTableBuilder(table, gateway, formatGatewayResult, queryTracer, config.experimental);
4676
+ const from = (table, options) => createTableBuilder(
4677
+ resolveTableNameForCall(table, options?.schema),
4678
+ gateway,
4679
+ formatGatewayResult,
4680
+ queryTracer,
4681
+ config.experimental
4682
+ );
4204
4683
  const rpc = (fn, args, options) => {
4205
4684
  const normalizedFn = fn.trim();
4206
4685
  if (!normalizedFn) {
@@ -4223,6 +4702,7 @@ function createClientFromConfig(config) {
4223
4702
  db,
4224
4703
  rpc,
4225
4704
  query,
4705
+ verifyConnection: gateway.verifyConnection,
4226
4706
  auth: auth.auth
4227
4707
  };
4228
4708
  }
@@ -4466,8 +4946,8 @@ var TypedAthenaClientImpl = class _TypedAthenaClientImpl {
4466
4946
  });
4467
4947
  this.db = this.baseClient.db;
4468
4948
  }
4469
- from(table) {
4470
- return this.baseClient.from(table);
4949
+ from(table, options) {
4950
+ return this.baseClient.from(table, options);
4471
4951
  }
4472
4952
  rpc(fn, args, options) {
4473
4953
  return this.baseClient.rpc(fn, args, options);
@@ -4475,6 +4955,9 @@ var TypedAthenaClientImpl = class _TypedAthenaClientImpl {
4475
4955
  query(query, options) {
4476
4956
  return this.baseClient.query(query, options);
4477
4957
  }
4958
+ verifyConnection(options) {
4959
+ return this.baseClient.verifyConnection(options);
4960
+ }
4478
4961
  withTenantContext(context) {
4479
4962
  return new _TypedAthenaClientImpl({
4480
4963
  registry: this.registry,
@@ -4771,6 +5254,7 @@ exports.isAthenaGatewayError = isAthenaGatewayError;
4771
5254
  exports.isOk = isOk;
4772
5255
  exports.loadGeneratorConfig = loadGeneratorConfig;
4773
5256
  exports.normalizeAthenaError = normalizeAthenaError;
5257
+ exports.normalizeAthenaGatewayBaseUrl = normalizeAthenaGatewayBaseUrl;
4774
5258
  exports.normalizeGeneratorConfig = normalizeGeneratorConfig;
4775
5259
  exports.normalizeSchemaSelection = normalizeSchemaSelection;
4776
5260
  exports.parseBooleanFlag = parseBooleanFlag2;
@@ -4786,6 +5270,7 @@ exports.toModelPayload = toModelPayload;
4786
5270
  exports.unwrap = unwrap;
4787
5271
  exports.unwrapOne = unwrapOne;
4788
5272
  exports.unwrapRows = unwrapRows;
5273
+ exports.verifyAthenaGatewayUrl = verifyAthenaGatewayUrl;
4789
5274
  exports.withRetry = withRetry;
4790
5275
  //# sourceMappingURL=browser.cjs.map
4791
5276
  //# sourceMappingURL=browser.cjs.map