@xylex-group/athena 2.1.2 → 2.3.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 (42) hide show
  1. package/README.md +287 -116
  2. package/dist/browser.cjs +1628 -156
  3. package/dist/browser.cjs.map +1 -1
  4. package/dist/browser.d.cts +14 -14
  5. package/dist/browser.d.ts +14 -14
  6. package/dist/browser.js +1625 -156
  7. package/dist/browser.js.map +1 -1
  8. package/dist/cli/index.cjs +1532 -145
  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 +1533 -146
  13. package/dist/cli/index.js.map +1 -1
  14. package/dist/index.cjs +1658 -167
  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 +1656 -168
  19. package/dist/index.js.map +1 -1
  20. package/dist/{model-form-2hqmoOUX.d.ts → model-form-BpDXlbxb.d.ts} +97 -2
  21. package/dist/{model-form-Cy-zaO0u.d.cts → model-form-hoE2jHIi.d.cts} +97 -2
  22. package/dist/{pipeline-BOPszLsL.d.ts → pipeline-BNIw8pDQ.d.ts} +1 -1
  23. package/dist/{pipeline-E3FDbs4W.d.cts → pipeline-DNIpEsN8.d.cts} +1 -1
  24. package/dist/{client-dpAp-NZK.d.cts → react-email-BvyCZnfW.d.cts} +349 -174
  25. package/dist/{client-BX0NQqOn.d.ts → react-email-qPA1wjFV.d.ts} +349 -174
  26. package/dist/react.cjs +30 -9
  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 +30 -9
  31. package/dist/react.js.map +1 -1
  32. package/dist/{types-BaBzjwXr.d.cts → types-A5e97acl.d.cts} +2 -1
  33. package/dist/{types-BaBzjwXr.d.ts → types-A5e97acl.d.ts} +2 -1
  34. package/dist/{types-CeBPrnGj.d.ts → types-BnD22-vb.d.ts} +1 -1
  35. package/dist/{types-CpqL-pZx.d.cts → types-bDlr4u7p.d.cts} +1 -1
  36. package/dist/utils.cjs +153 -0
  37. package/dist/utils.cjs.map +1 -0
  38. package/dist/utils.d.cts +23 -0
  39. package/dist/utils.d.ts +23 -0
  40. package/dist/utils.js +146 -0
  41. package/dist/utils.js.map +1 -0
  42. package/package.json +75 -17
package/dist/cli/index.js CHANGED
@@ -1,10 +1,15 @@
1
- import { mkdir, writeFile } from 'fs/promises';
1
+ import { mkdir, writeFile, stat } from 'fs/promises';
2
2
  import { resolve, dirname, posix } from 'path';
3
3
  import { existsSync, readFileSync } from 'fs';
4
4
  import { pathToFileURL } from 'url';
5
5
 
6
6
  // src/generator/pipeline.ts
7
7
 
8
+ // src/utils/slugify.ts
9
+ function slugify(input) {
10
+ return input.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
11
+ }
12
+
8
13
  // src/generator/naming.ts
9
14
  var IDENTIFIER_PATTERN = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
10
15
  var RESERVED_IDENTIFIERS = /* @__PURE__ */ new Set([
@@ -100,7 +105,7 @@ function applyNamingStyle(input, style) {
100
105
  case "snake":
101
106
  return words.map((word) => word.toLowerCase()).join("_");
102
107
  case "kebab":
103
- return words.map((word) => word.toLowerCase()).join("-");
108
+ return slugify(words.join("-"));
104
109
  default:
105
110
  return input;
106
111
  }
@@ -353,6 +358,19 @@ function isAthenaGatewayError(error) {
353
358
  return error instanceof AthenaGatewayError;
354
359
  }
355
360
 
361
+ // src/utils/parse-boolean-flag.ts
362
+ function parseBooleanFlag(rawValue, fallback) {
363
+ if (!rawValue) return fallback;
364
+ const normalized = rawValue.trim().toLowerCase();
365
+ if (normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on") {
366
+ return true;
367
+ }
368
+ if (normalized === "0" || normalized === "false" || normalized === "no" || normalized === "off") {
369
+ return false;
370
+ }
371
+ return fallback;
372
+ }
373
+
356
374
  // src/auxiliaries.ts
357
375
  var AthenaErrorCode = {
358
376
  UniqueViolation: "UNIQUE_VIOLATION",
@@ -373,20 +391,41 @@ var AthenaErrorCategory = {
373
391
  Database: "database",
374
392
  Unknown: "unknown"
375
393
  };
376
- function parseBooleanFlag(rawValue, fallback) {
377
- if (!rawValue) return fallback;
378
- const normalized = rawValue.trim().toLowerCase();
379
- if (normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on") {
380
- return true;
381
- }
382
- if (normalized === "0" || normalized === "false" || normalized === "no" || normalized === "off") {
383
- return false;
384
- }
385
- return fallback;
394
+ function parseBooleanFlag2(rawValue, fallback) {
395
+ return parseBooleanFlag(rawValue, fallback);
386
396
  }
387
397
  function isRecord(value) {
388
398
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
389
399
  }
400
+ function firstNonEmptyString(...values) {
401
+ for (const value of values) {
402
+ if (typeof value === "string" && value.trim().length > 0) {
403
+ return value.trim();
404
+ }
405
+ }
406
+ return void 0;
407
+ }
408
+ function messageFromUnknownError(error) {
409
+ if (typeof error === "string" && error.trim().length > 0) {
410
+ return error.trim();
411
+ }
412
+ if (error instanceof Error && error.message.trim().length > 0) {
413
+ return error.message.trim();
414
+ }
415
+ if (!isRecord(error)) {
416
+ return void 0;
417
+ }
418
+ return firstNonEmptyString(error.message, error.error, error.details);
419
+ }
420
+ function gatewayCodeFromUnknownError(error) {
421
+ if (!isRecord(error) || typeof error.gatewayCode !== "string") {
422
+ return void 0;
423
+ }
424
+ return error.gatewayCode;
425
+ }
426
+ function isAthenaResultErrorLike(value) {
427
+ return isRecord(value) && typeof value.message === "string" && (value.athenaCode === void 0 || isAthenaErrorCode(value.athenaCode)) && (value.kind === void 0 || isAthenaErrorKind(value.kind)) && (value.category === void 0 || isAthenaErrorCategory(value.category)) && (value.retryable === void 0 || typeof value.retryable === "boolean") && (value.status === void 0 || typeof value.status === "number");
428
+ }
390
429
  function isAthenaErrorKind(value) {
391
430
  return value === "unique_violation" || value === "not_found" || value === "validation" || value === "auth" || value === "rate_limit" || value === "transient" || value === "unknown";
392
431
  }
@@ -508,13 +547,50 @@ function normalizeAthenaError(resultOrError, context) {
508
547
  return withContextOverrides(attached, context);
509
548
  }
510
549
  if (isAthenaResultLike(resultOrError)) {
550
+ if (isAthenaResultErrorLike(resultOrError.error)) {
551
+ return {
552
+ kind: resultOrError.error.kind ?? classifyKind(resultOrError.status, gatewayCodeFromUnknownError(resultOrError.error), resultOrError.error.message),
553
+ code: resultOrError.error.athenaCode ?? toAthenaErrorCode(
554
+ resultOrError.error.kind ?? classifyKind(
555
+ resultOrError.status,
556
+ gatewayCodeFromUnknownError(resultOrError.error),
557
+ resultOrError.error.message
558
+ ),
559
+ resultOrError.error.status ?? resultOrError.status,
560
+ gatewayCodeFromUnknownError(resultOrError.error)
561
+ ),
562
+ category: resultOrError.error.category ?? toAthenaErrorCategory(
563
+ resultOrError.error.kind ?? classifyKind(
564
+ resultOrError.status,
565
+ gatewayCodeFromUnknownError(resultOrError.error),
566
+ resultOrError.error.message
567
+ ),
568
+ resultOrError.error.status ?? resultOrError.status
569
+ ),
570
+ retryable: resultOrError.error.retryable ?? isRetryable(
571
+ resultOrError.error.kind ?? classifyKind(
572
+ resultOrError.status,
573
+ gatewayCodeFromUnknownError(resultOrError.error),
574
+ resultOrError.error.message
575
+ ),
576
+ resultOrError.error.status ?? resultOrError.status
577
+ ),
578
+ status: resultOrError.error.status ?? resultOrError.status,
579
+ constraint: resultOrError.error.constraint,
580
+ table: context?.table ?? resultOrError.error.table,
581
+ operation: context?.operation ?? resultOrError.error.operation,
582
+ message: resultOrError.error.message,
583
+ raw: resultOrError.error.raw ?? resultOrError.raw
584
+ };
585
+ }
511
586
  const details = resultOrError.errorDetails;
512
- const message2 = resultOrError.error ?? details?.message ?? `Athena ${context?.operation ?? operationFromDetails(details) ?? "request"} failed`;
587
+ const message2 = messageFromUnknownError(resultOrError.error) ?? details?.message ?? `Athena ${context?.operation ?? operationFromDetails(details) ?? "request"} failed`;
513
588
  const operation = context?.operation ?? operationFromDetails(details);
514
589
  const table = context?.table ?? extractTable(message2);
515
590
  const constraint = extractConstraint(message2);
516
- const kind2 = classifyKind(resultOrError.status, details?.code, message2);
517
- const code = toAthenaErrorCode(kind2, resultOrError.status, details?.code);
591
+ const gatewayCode = details?.code ?? gatewayCodeFromUnknownError(resultOrError.error);
592
+ const kind2 = classifyKind(resultOrError.status, gatewayCode, message2);
593
+ const code = toAthenaErrorCode(kind2, resultOrError.status, gatewayCode);
518
594
  const category = toAthenaErrorCategory(kind2, resultOrError.status);
519
595
  return {
520
596
  kind: kind2,
@@ -792,7 +868,7 @@ function normalizeBooleanFlag(rawValue, fallback) {
792
868
  return rawValue;
793
869
  }
794
870
  if (typeof rawValue === "string") {
795
- return parseBooleanFlag(rawValue, fallback);
871
+ return parseBooleanFlag2(rawValue, fallback);
796
872
  }
797
873
  return fallback;
798
874
  }
@@ -1309,23 +1385,39 @@ function normalizeHeaderValue(value) {
1309
1385
  function isRecord2(value) {
1310
1386
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1311
1387
  }
1388
+ function nonEmptyString(value) {
1389
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
1390
+ }
1391
+ function resolveStructuredErrorPayload(payload) {
1392
+ if (!isRecord2(payload)) return null;
1393
+ return isRecord2(payload.error) ? payload.error : payload;
1394
+ }
1312
1395
  function resolveRequestId(headers) {
1313
1396
  return headers.get("x-request-id") ?? headers.get("x-correlation-id") ?? headers.get("x-athena-request-id") ?? void 0;
1314
1397
  }
1315
1398
  function resolveErrorMessage(payload, fallback) {
1316
- if (isRecord2(payload)) {
1317
- const messageCandidates = [payload.error, payload.message, payload.details];
1399
+ const structuredPayload = resolveStructuredErrorPayload(payload);
1400
+ if (structuredPayload) {
1401
+ const messageCandidates = [structuredPayload.message, structuredPayload.error, structuredPayload.details];
1318
1402
  for (const candidate of messageCandidates) {
1319
- if (typeof candidate === "string" && candidate.trim().length > 0) {
1320
- return candidate.trim();
1321
- }
1403
+ const resolved = nonEmptyString(candidate);
1404
+ if (resolved) return resolved;
1322
1405
  }
1323
1406
  }
1324
- if (typeof payload === "string" && payload.trim().length > 0) {
1325
- return payload.trim();
1326
- }
1407
+ const rawMessage = nonEmptyString(payload);
1408
+ if (rawMessage) return rawMessage;
1327
1409
  return fallback;
1328
1410
  }
1411
+ function resolveErrorHint(payload) {
1412
+ const structuredPayload = resolveStructuredErrorPayload(payload);
1413
+ return structuredPayload ? nonEmptyString(structuredPayload.hint) : void 0;
1414
+ }
1415
+ function resolveStatusText(response, payload) {
1416
+ const rawStatusText = nonEmptyString(response.statusText);
1417
+ if (rawStatusText) return rawStatusText;
1418
+ const payloadRecord = isRecord2(payload) ? payload : null;
1419
+ return payloadRecord ? nonEmptyString(payloadRecord.statusText) ?? null : null;
1420
+ }
1329
1421
  function detailsFromError(error) {
1330
1422
  return error.toDetails();
1331
1423
  }
@@ -1496,6 +1588,7 @@ async function callAthena(config, endpoint, method, payload, options) {
1496
1588
  return {
1497
1589
  ok: false,
1498
1590
  status: response.status,
1591
+ statusText: resolveStatusText(response, parsedBody.parsed),
1499
1592
  data: null,
1500
1593
  error: invalidJsonError.message,
1501
1594
  errorDetails: detailsFromError(invalidJsonError),
@@ -1514,11 +1607,13 @@ async function callAthena(config, endpoint, method, payload, options) {
1514
1607
  status: response.status,
1515
1608
  endpoint,
1516
1609
  method,
1517
- requestId
1610
+ requestId,
1611
+ hint: resolveErrorHint(parsed)
1518
1612
  });
1519
1613
  return {
1520
1614
  ok: false,
1521
1615
  status: response.status,
1616
+ statusText: resolveStatusText(response, parsed),
1522
1617
  data: null,
1523
1618
  error: httpError.message,
1524
1619
  errorDetails: detailsFromError(httpError),
@@ -1530,6 +1625,7 @@ async function callAthena(config, endpoint, method, payload, options) {
1530
1625
  return {
1531
1626
  ok: true,
1532
1627
  status: response.status,
1628
+ statusText: resolveStatusText(response, parsed),
1533
1629
  data: payloadData ?? null,
1534
1630
  count: payloadCount,
1535
1631
  error: void 0,
@@ -1549,6 +1645,7 @@ async function callAthena(config, endpoint, method, payload, options) {
1549
1645
  return {
1550
1646
  ok: false,
1551
1647
  status: 0,
1648
+ statusText: null,
1552
1649
  data: null,
1553
1650
  error: networkError.message,
1554
1651
  errorDetails: detailsFromError(networkError),
@@ -1590,10 +1687,29 @@ function createAthenaGatewayClient(config = {}) {
1590
1687
  // src/sql-identifiers.ts
1591
1688
  var SIMPLE_IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
1592
1689
  var COMPOSITE_IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/;
1593
- var ALIAS_PATTERN = /^([A-Za-z_][A-Za-z0-9_.]*)\s+(?:as\s+)?([A-Za-z_][A-Za-z0-9_]*)$/i;
1690
+ var SQL_ALIAS_PATTERN = /^([A-Za-z_][A-Za-z0-9_.]*)\s+(?:as\s+)?([A-Za-z_][A-Za-z0-9_]*)$/i;
1691
+ var RESPONSE_ALIAS_PATTERN = /^([A-Za-z_][A-Za-z0-9_]*)\s*:\s*([A-Za-z_][A-Za-z0-9_.]*)$/i;
1594
1692
  function quoteIdentifierSegment(identifier) {
1595
1693
  return `"${identifier.replace(/"/g, '""')}"`;
1596
1694
  }
1695
+ function parseAliasedIdentifierToken(token) {
1696
+ const responseAliasMatch = RESPONSE_ALIAS_PATTERN.exec(token);
1697
+ if (responseAliasMatch) {
1698
+ const [, aliasIdentifier2, baseIdentifier2] = responseAliasMatch;
1699
+ if (COMPOSITE_IDENTIFIER_PATTERN.test(baseIdentifier2) && SIMPLE_IDENTIFIER_PATTERN.test(aliasIdentifier2)) {
1700
+ return { baseIdentifier: baseIdentifier2, aliasIdentifier: aliasIdentifier2 };
1701
+ }
1702
+ }
1703
+ const sqlAliasMatch = SQL_ALIAS_PATTERN.exec(token);
1704
+ if (!sqlAliasMatch) {
1705
+ return null;
1706
+ }
1707
+ const [, baseIdentifier, aliasIdentifier] = sqlAliasMatch;
1708
+ if (!COMPOSITE_IDENTIFIER_PATTERN.test(baseIdentifier) || !SIMPLE_IDENTIFIER_PATTERN.test(aliasIdentifier)) {
1709
+ return null;
1710
+ }
1711
+ return { baseIdentifier, aliasIdentifier };
1712
+ }
1597
1713
  function quoteQualifiedIdentifier(identifier) {
1598
1714
  return identifier.split(".").map((segment) => quoteIdentifierSegment(segment)).join(".");
1599
1715
  }
@@ -1602,23 +1718,27 @@ function quoteSelectToken(token) {
1602
1718
  if (COMPOSITE_IDENTIFIER_PATTERN.test(token)) {
1603
1719
  return quoteQualifiedIdentifier(token);
1604
1720
  }
1605
- const aliasMatch = ALIAS_PATTERN.exec(token);
1606
- if (!aliasMatch) {
1607
- return token;
1608
- }
1609
- const [, baseIdentifier, aliasIdentifier] = aliasMatch;
1610
- if (!COMPOSITE_IDENTIFIER_PATTERN.test(baseIdentifier) || !SIMPLE_IDENTIFIER_PATTERN.test(aliasIdentifier)) {
1721
+ const aliasedIdentifier = parseAliasedIdentifierToken(token);
1722
+ if (!aliasedIdentifier) {
1611
1723
  return token;
1612
1724
  }
1725
+ const { baseIdentifier, aliasIdentifier } = aliasedIdentifier;
1613
1726
  return `${quoteQualifiedIdentifier(baseIdentifier)} AS ${quoteIdentifierSegment(aliasIdentifier)}`;
1614
1727
  }
1728
+ function quoteSelectColumnToken(token) {
1729
+ const trimmed = token.trim();
1730
+ if (!trimmed || trimmed === "*") return trimmed || "*";
1731
+ const responseAliasMatch = RESPONSE_ALIAS_PATTERN.exec(trimmed);
1732
+ if (responseAliasMatch) {
1733
+ const [, aliasIdentifier, baseIdentifier] = responseAliasMatch;
1734
+ return `${quoteQualifiedIdentifier(baseIdentifier)} AS ${quoteIdentifierSegment(aliasIdentifier)}`;
1735
+ }
1736
+ return quoteQualifiedIdentifier(trimmed);
1737
+ }
1615
1738
  function canAutoQuoteToken(token) {
1616
1739
  if (token === "*") return true;
1617
1740
  if (COMPOSITE_IDENTIFIER_PATTERN.test(token)) return true;
1618
- const aliasMatch = ALIAS_PATTERN.exec(token);
1619
- if (!aliasMatch) return false;
1620
- const [, baseIdentifier, aliasIdentifier] = aliasMatch;
1621
- return COMPOSITE_IDENTIFIER_PATTERN.test(baseIdentifier) && SIMPLE_IDENTIFIER_PATTERN.test(aliasIdentifier);
1741
+ return parseAliasedIdentifierToken(token) != null;
1622
1742
  }
1623
1743
  function splitTopLevelCommaSeparated(input) {
1624
1744
  const parts = [];
@@ -1702,6 +1822,190 @@ function quoteSelectColumnsExpression(columns) {
1702
1822
  return tokens.map(quoteSelectToken).join(", ");
1703
1823
  }
1704
1824
 
1825
+ // src/auth/react-email.ts
1826
+ var reactEmailRenderModulePromise;
1827
+ function isRecord3(value) {
1828
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1829
+ }
1830
+ function isFunction(value) {
1831
+ return typeof value === "function";
1832
+ }
1833
+ function toStringOrUndefined(value) {
1834
+ if (typeof value !== "string") return void 0;
1835
+ return value;
1836
+ }
1837
+ function nowIsoString() {
1838
+ return (/* @__PURE__ */ new Date()).toISOString();
1839
+ }
1840
+ function emitReactEmailEvent(observe, phase, input = {}) {
1841
+ if (!observe) return;
1842
+ try {
1843
+ observe({
1844
+ phase,
1845
+ timestamp: nowIsoString(),
1846
+ ...input
1847
+ });
1848
+ } catch {
1849
+ }
1850
+ }
1851
+ function mergeRenderDefaults(input, defaults) {
1852
+ return {
1853
+ ...input,
1854
+ pretty: input.pretty ?? defaults?.pretty,
1855
+ includePlainText: input.includePlainText ?? defaults?.includePlainText
1856
+ };
1857
+ }
1858
+ function mergeRuntimeOptions(options) {
1859
+ if (!options) return void 0;
1860
+ return {
1861
+ defaults: options.defaults,
1862
+ observe: options.observe,
1863
+ route: "route" in options ? options.route : void 0
1864
+ };
1865
+ }
1866
+ async function resolveReactEmailRenderModule() {
1867
+ if (!reactEmailRenderModulePromise) {
1868
+ reactEmailRenderModulePromise = (async () => {
1869
+ try {
1870
+ const loaded = await import('@react-email/render');
1871
+ if (!isFunction(loaded.render)) {
1872
+ throw new Error("missing render(...) export");
1873
+ }
1874
+ return {
1875
+ render: loaded.render,
1876
+ toPlainText: isFunction(loaded.toPlainText) ? loaded.toPlainText : void 0,
1877
+ pretty: isFunction(loaded.pretty) ? loaded.pretty : void 0
1878
+ };
1879
+ } catch (error) {
1880
+ const message = error instanceof Error ? error.message : String(error);
1881
+ throw new Error(
1882
+ `React Email rendering requires @react-email/render. Install it in your project (for example: pnpm add @react-email/render). Loader error: ${message}`
1883
+ );
1884
+ }
1885
+ })();
1886
+ }
1887
+ if (!reactEmailRenderModulePromise) {
1888
+ throw new Error("React Email renderer module failed to initialize");
1889
+ }
1890
+ return reactEmailRenderModulePromise;
1891
+ }
1892
+ async function resolveReactEmailElement(input) {
1893
+ if (input.element != null) {
1894
+ return input.element;
1895
+ }
1896
+ if (!input.component) {
1897
+ throw new Error("react email payload requires either `element` or `component`");
1898
+ }
1899
+ try {
1900
+ const reactModule = await import('react');
1901
+ if (typeof reactModule.createElement !== "function") {
1902
+ throw new Error("react createElement(...) export is unavailable");
1903
+ }
1904
+ return reactModule.createElement(
1905
+ input.component,
1906
+ input.props ?? {}
1907
+ );
1908
+ } catch (error) {
1909
+ const message = error instanceof Error ? error.message : String(error);
1910
+ throw new Error(
1911
+ `React Email component rendering requires react runtime support. Install react in your project. Loader error: ${message}`
1912
+ );
1913
+ }
1914
+ }
1915
+ async function renderAthenaReactEmail(input, options) {
1916
+ if (!isRecord3(input)) {
1917
+ throw new Error("react email payload must be an object");
1918
+ }
1919
+ const runtimeOptions = mergeRuntimeOptions(options);
1920
+ const start = Date.now();
1921
+ emitReactEmailEvent(runtimeOptions?.observe, "render:start", {
1922
+ route: runtimeOptions?.route,
1923
+ message: "Rendering react email payload"
1924
+ });
1925
+ try {
1926
+ const normalizedInput = mergeRenderDefaults(input, runtimeOptions?.defaults);
1927
+ const element = await resolveReactEmailElement(normalizedInput);
1928
+ const renderModule = await resolveReactEmailRenderModule();
1929
+ const htmlValue = await renderModule.render(element);
1930
+ const renderedHtml = typeof htmlValue === "string" ? htmlValue : String(htmlValue ?? "");
1931
+ if (!renderedHtml.trim()) {
1932
+ throw new Error("react email renderer returned an empty HTML string");
1933
+ }
1934
+ let html = renderedHtml;
1935
+ if (normalizedInput.pretty && renderModule.pretty) {
1936
+ const prettyValue = await renderModule.pretty(renderedHtml);
1937
+ if (typeof prettyValue === "string" && prettyValue.trim().length > 0) {
1938
+ html = prettyValue;
1939
+ }
1940
+ }
1941
+ const explicitText = toStringOrUndefined(normalizedInput.text);
1942
+ if (explicitText !== void 0) {
1943
+ emitReactEmailEvent(runtimeOptions?.observe, "render:success", {
1944
+ route: runtimeOptions?.route,
1945
+ durationMs: Date.now() - start,
1946
+ message: "Rendered react email with explicit text"
1947
+ });
1948
+ return {
1949
+ html,
1950
+ text: explicitText
1951
+ };
1952
+ }
1953
+ if (normalizedInput.includePlainText === false || !renderModule.toPlainText) {
1954
+ emitReactEmailEvent(runtimeOptions?.observe, "render:success", {
1955
+ route: runtimeOptions?.route,
1956
+ durationMs: Date.now() - start,
1957
+ message: "Rendered react email without plain-text derivation"
1958
+ });
1959
+ return { html };
1960
+ }
1961
+ const plainTextValue = await renderModule.toPlainText(html);
1962
+ const plainText = toStringOrUndefined(plainTextValue);
1963
+ emitReactEmailEvent(runtimeOptions?.observe, "render:success", {
1964
+ route: runtimeOptions?.route,
1965
+ durationMs: Date.now() - start,
1966
+ message: plainText ? "Rendered react email with derived plain text" : "Rendered react email HTML only"
1967
+ });
1968
+ if (plainText === void 0) {
1969
+ return { html };
1970
+ }
1971
+ return {
1972
+ html,
1973
+ text: plainText
1974
+ };
1975
+ } catch (error) {
1976
+ const message = error instanceof Error ? error.message : String(error);
1977
+ emitReactEmailEvent(runtimeOptions?.observe, "render:error", {
1978
+ route: runtimeOptions?.route,
1979
+ durationMs: Date.now() - start,
1980
+ error: message,
1981
+ message: "Failed to render react email payload"
1982
+ });
1983
+ throw error;
1984
+ }
1985
+ }
1986
+ async function resolveReactEmailPayloadFields(input, fields, options) {
1987
+ const { react, ...payloadWithoutReact } = input;
1988
+ if (!react) {
1989
+ return payloadWithoutReact;
1990
+ }
1991
+ const rendered = await renderAthenaReactEmail(react, options);
1992
+ const payload = {
1993
+ ...payloadWithoutReact
1994
+ };
1995
+ payload[fields.htmlField] = rendered.html;
1996
+ const currentTextValue = payload[fields.textField];
1997
+ if (rendered.text !== void 0 && (currentTextValue === void 0 || currentTextValue === null || currentTextValue === "")) {
1998
+ payload[fields.textField] = rendered.text;
1999
+ }
2000
+ if (fields.variablesField && (payload[fields.variablesField] === void 0 || payload[fields.variablesField] === null) && isRecord3(react.props)) {
2001
+ const derivedVariables = Object.keys(react.props);
2002
+ if (derivedVariables.length > 0) {
2003
+ payload[fields.variablesField] = derivedVariables;
2004
+ }
2005
+ }
2006
+ return payload;
2007
+ }
2008
+
1705
2009
  // src/auth/client.ts
1706
2010
  var DEFAULT_AUTH_BASE_URL = "http://localhost:3001/api/auth";
1707
2011
  var FALLBACK_SDK_VERSION2 = "1.0.0";
@@ -1711,7 +2015,7 @@ var SDK_HEADER_VALUE2 = `${SDK_NAME2} ${SDK_VERSION2}`;
1711
2015
  function normalizeBaseUrl(baseUrl) {
1712
2016
  return (baseUrl ?? DEFAULT_AUTH_BASE_URL).replace(/\/$/, "");
1713
2017
  }
1714
- function isRecord3(value) {
2018
+ function isRecord4(value) {
1715
2019
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1716
2020
  }
1717
2021
  function normalizeHeaderValue2(value) {
@@ -1736,7 +2040,7 @@ function resolveRequestId2(headers) {
1736
2040
  return headers.get("x-request-id") ?? headers.get("x-correlation-id") ?? headers.get("x-athena-request-id") ?? void 0;
1737
2041
  }
1738
2042
  function resolveErrorMessage2(payload, fallback) {
1739
- if (isRecord3(payload)) {
2043
+ if (isRecord4(payload)) {
1740
2044
  const messageCandidates = [payload.error, payload.message, payload.details];
1741
2045
  for (const candidate of messageCandidates) {
1742
2046
  if (typeof candidate === "string" && candidate.trim().length > 0) {
@@ -2062,6 +2366,19 @@ function createAuthClient(config = {}) {
2062
2366
  options
2063
2367
  );
2064
2368
  };
2369
+ const withReactEmailRoute = (route) => ({
2370
+ ...resolvedConfig.reactEmail,
2371
+ route
2372
+ });
2373
+ const resolveAdminEmailPayload = (route, input) => resolveReactEmailPayloadFields(input, {
2374
+ htmlField: "htmlBody",
2375
+ textField: "textBody"
2376
+ }, withReactEmailRoute(route));
2377
+ const resolveAdminEmailTemplatePayload = (route, input) => resolveReactEmailPayloadFields(input, {
2378
+ htmlField: "htmlTemplate",
2379
+ textField: "textTemplate",
2380
+ variablesField: "variables"
2381
+ }, withReactEmailRoute(route));
2065
2382
  const listUserEmailsWithFallback = async (input, options) => {
2066
2383
  const primary = await getWithQuery(
2067
2384
  "/email/list",
@@ -2089,7 +2406,7 @@ function createAuthClient(config = {}) {
2089
2406
  data: null
2090
2407
  };
2091
2408
  }
2092
- const fallbackStatus = isRecord3(fallback.data) && typeof fallback.data.ok === "boolean" ? fallback.data.ok ? "ok" : "error" : "ok";
2409
+ const fallbackStatus = isRecord4(fallback.data) && typeof fallback.data.ok === "boolean" ? fallback.data.ok ? "ok" : "error" : "ok";
2093
2410
  return {
2094
2411
  ...fallback,
2095
2412
  data: {
@@ -2525,8 +2842,16 @@ function createAuthClient(config = {}) {
2525
2842
  email: {
2526
2843
  list: (input, options) => getWithQuery("/admin/email/list", input, options),
2527
2844
  get: (input, options) => getWithQuery("/admin/email/get", input, options),
2528
- create: (input, options) => postGeneric("/admin/email/create", input, options),
2529
- update: (input, options) => postGeneric("/admin/email/update", input, options),
2845
+ create: async (input, options) => postGeneric(
2846
+ "/admin/email/create",
2847
+ await resolveAdminEmailPayload("/admin/email/create", input),
2848
+ options
2849
+ ),
2850
+ update: async (input, options) => postGeneric(
2851
+ "/admin/email/update",
2852
+ await resolveAdminEmailPayload("/admin/email/update", input),
2853
+ options
2854
+ ),
2530
2855
  delete: (input, options) => postGeneric("/admin/email/delete", input, options),
2531
2856
  failure: {
2532
2857
  list: (input, options) => getWithQuery("/admin/email-failure/list", input, options),
@@ -2538,17 +2863,33 @@ function createAuthClient(config = {}) {
2538
2863
  template: {
2539
2864
  list: (input, options) => getWithQuery("/admin/email-template/list", input, options),
2540
2865
  get: (input, options) => getWithQuery("/admin/email-template/get", input, options),
2541
- create: (input, options) => postGeneric("/admin/email-template/create", input, options),
2542
- update: (input, options) => postGeneric("/admin/email-template/update", input, options),
2866
+ create: async (input, options) => postGeneric(
2867
+ "/admin/email-template/create",
2868
+ await resolveAdminEmailTemplatePayload("/admin/email-template/create", input),
2869
+ options
2870
+ ),
2871
+ update: async (input, options) => postGeneric(
2872
+ "/admin/email-template/update",
2873
+ await resolveAdminEmailTemplatePayload("/admin/email-template/update", input),
2874
+ options
2875
+ ),
2543
2876
  delete: (input, options) => postGeneric("/admin/email-template/delete", input, options)
2544
2877
  }
2545
2878
  },
2546
2879
  emailTemplate: {
2547
2880
  get: (input, options) => getWithQuery("/admin/email-template/get", input, options),
2548
- create: (input, options) => postGeneric("/admin/email-template/create", input, options),
2881
+ create: async (input, options) => postGeneric(
2882
+ "/admin/email-template/create",
2883
+ await resolveAdminEmailTemplatePayload("/admin/email-template/create", input),
2884
+ options
2885
+ ),
2549
2886
  delete: (input, options) => postGeneric("/admin/email-template/delete", input, options),
2550
2887
  list: (input, options) => getWithQuery("/admin/email-template/list", input, options),
2551
- update: (input, options) => postGeneric("/admin/email-template/update", input, options)
2888
+ update: async (input, options) => postGeneric(
2889
+ "/admin/email-template/update",
2890
+ await resolveAdminEmailTemplatePayload("/admin/email-template/update", input),
2891
+ options
2892
+ )
2552
2893
  }
2553
2894
  },
2554
2895
  apiKey: {
@@ -2771,17 +3112,282 @@ function createDbModule(input) {
2771
3112
  return db;
2772
3113
  }
2773
3114
 
3115
+ // src/query-ast.ts
3116
+ var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
3117
+ var FILTER_OPERATORS = /* @__PURE__ */ new Set([
3118
+ "eq",
3119
+ "neq",
3120
+ "gt",
3121
+ "gte",
3122
+ "lt",
3123
+ "lte",
3124
+ "like",
3125
+ "ilike",
3126
+ "is",
3127
+ "in",
3128
+ "contains",
3129
+ "containedBy"
3130
+ ]);
3131
+ var BOOLEAN_SAFE_OPERATORS = /* @__PURE__ */ new Set([
3132
+ "eq",
3133
+ "neq",
3134
+ "gt",
3135
+ "gte",
3136
+ "lt",
3137
+ "lte",
3138
+ "like",
3139
+ "ilike",
3140
+ "is"
3141
+ ]);
3142
+ function isRecord5(value) {
3143
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
3144
+ }
3145
+ function isUuidString(value) {
3146
+ return UUID_PATTERN.test(value.trim());
3147
+ }
3148
+ function isUuidIdentifierColumn(column) {
3149
+ return column === "id" || /(?:^|_)uuid(?:_|$)/i.test(column) || /_id$/i.test(column);
3150
+ }
3151
+ function shouldUseUuidTextComparison(column, value) {
3152
+ return typeof value === "string" && isUuidString(value) && isUuidIdentifierColumn(column);
3153
+ }
3154
+ function isRelationSelectNode(value) {
3155
+ return isRecord5(value) && isRecord5(value.select);
3156
+ }
3157
+ function normalizeIdentifier(value, label) {
3158
+ const normalized = value.trim();
3159
+ if (!normalized) {
3160
+ throw new Error(`${label} must be a non-empty string`);
3161
+ }
3162
+ return normalized;
3163
+ }
3164
+ function stringifyFilterValue(value) {
3165
+ if (Array.isArray(value)) {
3166
+ return value.join(",");
3167
+ }
3168
+ return String(value);
3169
+ }
3170
+ function buildGatewayCondition(operator, column, value) {
3171
+ const condition = { operator };
3172
+ if (column) {
3173
+ condition.column = column;
3174
+ if (operator === "eq") {
3175
+ condition.eq_column = column;
3176
+ }
3177
+ }
3178
+ if (value !== void 0) {
3179
+ condition.value = value;
3180
+ if (operator === "eq") {
3181
+ condition.eq_value = value;
3182
+ }
3183
+ }
3184
+ if (operator === "eq" && column && value !== void 0 && shouldUseUuidTextComparison(column, value)) {
3185
+ condition.column_cast = "text";
3186
+ condition.eq_column_cast = "text";
3187
+ }
3188
+ return condition;
3189
+ }
3190
+ function compileRelationToken(key, node) {
3191
+ const nested = compileSelectShape(node.select);
3192
+ const propertyKey = normalizeIdentifier(key, "select relation key");
3193
+ const relationToken = normalizeIdentifier(node.via ?? propertyKey, "select relation token");
3194
+ const alias = node.as?.trim() || (relationToken !== propertyKey ? propertyKey : "");
3195
+ const prefix = alias ? `${alias}:` : "";
3196
+ return `${prefix}${relationToken}(${nested})`;
3197
+ }
3198
+ function compileSelectShape(select) {
3199
+ if (!isRecord5(select)) {
3200
+ throw new Error("findMany select must be an object");
3201
+ }
3202
+ const tokens = [];
3203
+ for (const [rawKey, rawValue] of Object.entries(select)) {
3204
+ if (rawValue === void 0) {
3205
+ continue;
3206
+ }
3207
+ if (rawValue === true) {
3208
+ tokens.push(normalizeIdentifier(rawKey, "select column"));
3209
+ continue;
3210
+ }
3211
+ if (isRelationSelectNode(rawValue)) {
3212
+ tokens.push(compileRelationToken(rawKey, rawValue));
3213
+ continue;
3214
+ }
3215
+ throw new Error(`Unsupported select node for "${rawKey}"`);
3216
+ }
3217
+ if (tokens.length === 0) {
3218
+ throw new Error("findMany select requires at least one field");
3219
+ }
3220
+ return tokens.join(",");
3221
+ }
3222
+ function compileColumnWhere(column, input) {
3223
+ const normalizedColumn = normalizeIdentifier(column, "where column");
3224
+ if (!isRecord5(input)) {
3225
+ return [buildGatewayCondition("eq", normalizedColumn, input)];
3226
+ }
3227
+ const conditions = [];
3228
+ for (const [rawOperator, rawValue] of Object.entries(input)) {
3229
+ if (rawValue === void 0) {
3230
+ continue;
3231
+ }
3232
+ if (!FILTER_OPERATORS.has(rawOperator)) {
3233
+ throw new Error(`Unsupported where operator "${rawOperator}" on "${normalizedColumn}"`);
3234
+ }
3235
+ if ((rawOperator === "in" || rawOperator === "contains" || rawOperator === "containedBy") && !Array.isArray(rawValue)) {
3236
+ throw new Error(`where.${normalizedColumn}.${rawOperator} requires an array value`);
3237
+ }
3238
+ conditions.push(
3239
+ buildGatewayCondition(
3240
+ rawOperator,
3241
+ normalizedColumn,
3242
+ rawValue
3243
+ )
3244
+ );
3245
+ }
3246
+ if (conditions.length === 0) {
3247
+ throw new Error(`where.${normalizedColumn} requires at least one operator`);
3248
+ }
3249
+ return conditions;
3250
+ }
3251
+ function compileBooleanExpressionTerms(clause, label) {
3252
+ if (!isRecord5(clause)) {
3253
+ throw new Error(`findMany where.${label} clauses must be objects`);
3254
+ }
3255
+ const entries = Object.entries(clause).filter(([, value]) => value !== void 0);
3256
+ if (entries.length !== 1) {
3257
+ throw new Error(`findMany where.${label} clauses must target exactly one column`);
3258
+ }
3259
+ const [rawColumn, rawValue] = entries[0];
3260
+ const column = normalizeIdentifier(rawColumn, `where.${label} column`);
3261
+ if (!isRecord5(rawValue)) {
3262
+ return [`${column}.eq.${stringifyFilterValue(rawValue)}`];
3263
+ }
3264
+ const operatorEntries = Object.entries(rawValue).filter(([, value]) => value !== void 0);
3265
+ if (operatorEntries.length === 0) {
3266
+ throw new Error(`findMany where.${label}.${column} requires at least one operator`);
3267
+ }
3268
+ if (label === "not" && operatorEntries.length > 1) {
3269
+ throw new Error("findMany where.not only supports a single lossless operator expression");
3270
+ }
3271
+ return operatorEntries.map(([rawOperator, rawOperand]) => {
3272
+ if (!BOOLEAN_SAFE_OPERATORS.has(rawOperator)) {
3273
+ throw new Error(`findMany where.${label} only supports lossless scalar operators`);
3274
+ }
3275
+ if (Array.isArray(rawOperand)) {
3276
+ throw new Error(`findMany where.${label} does not support array-valued operators`);
3277
+ }
3278
+ return `${column}.${rawOperator}.${stringifyFilterValue(rawOperand)}`;
3279
+ });
3280
+ }
3281
+ function compileWhere(where) {
3282
+ if (where === void 0) {
3283
+ return void 0;
3284
+ }
3285
+ if (!isRecord5(where)) {
3286
+ throw new Error("findMany where must be an object");
3287
+ }
3288
+ const conditions = [];
3289
+ for (const [rawKey, rawValue] of Object.entries(where)) {
3290
+ if (rawValue === void 0) {
3291
+ continue;
3292
+ }
3293
+ if (rawKey === "or") {
3294
+ if (!Array.isArray(rawValue) || rawValue.length === 0) {
3295
+ throw new Error("findMany where.or must be a non-empty array");
3296
+ }
3297
+ const expressions = rawValue.flatMap(
3298
+ (value) => compileBooleanExpressionTerms(value, "or")
3299
+ );
3300
+ conditions.push(buildGatewayCondition("or", void 0, expressions.join(",")));
3301
+ continue;
3302
+ }
3303
+ if (rawKey === "not") {
3304
+ const expressions = compileBooleanExpressionTerms(rawValue, "not");
3305
+ if (expressions.length !== 1) {
3306
+ throw new Error("findMany where.not must compile to exactly one lossless expression");
3307
+ }
3308
+ conditions.push(buildGatewayCondition("not", void 0, expressions[0]));
3309
+ continue;
3310
+ }
3311
+ conditions.push(...compileColumnWhere(rawKey, rawValue));
3312
+ }
3313
+ return conditions.length > 0 ? conditions : void 0;
3314
+ }
3315
+ function resolveOrderDirection(input) {
3316
+ if (typeof input === "boolean") {
3317
+ return input === false ? "descending" : "ascending";
3318
+ }
3319
+ if (typeof input === "string") {
3320
+ const normalized = input.trim().toLowerCase();
3321
+ if (normalized === "asc" || normalized === "ascending") {
3322
+ return "ascending";
3323
+ }
3324
+ if (normalized === "desc" || normalized === "descending") {
3325
+ return "descending";
3326
+ }
3327
+ throw new Error(`Unsupported orderBy direction "${input}"`);
3328
+ }
3329
+ return input.ascending === false ? "descending" : "ascending";
3330
+ }
3331
+ function compileOrderBy(orderBy) {
3332
+ if (orderBy === void 0) {
3333
+ return void 0;
3334
+ }
3335
+ if (!isRecord5(orderBy)) {
3336
+ throw new Error("findMany orderBy must be an object");
3337
+ }
3338
+ if ("column" in orderBy) {
3339
+ return {
3340
+ field: normalizeIdentifier(String(orderBy.column), "orderBy column"),
3341
+ direction: orderBy.ascending === false ? "descending" : "ascending"
3342
+ };
3343
+ }
3344
+ const entries = Object.entries(orderBy).filter(([, value]) => value !== void 0);
3345
+ if (entries.length === 0) {
3346
+ return void 0;
3347
+ }
3348
+ if (entries.length > 1) {
3349
+ throw new Error("findMany orderBy only supports a single column in v1");
3350
+ }
3351
+ const [column, input] = entries[0];
3352
+ return {
3353
+ field: normalizeIdentifier(column, "orderBy column"),
3354
+ direction: resolveOrderDirection(input)
3355
+ };
3356
+ }
3357
+
2774
3358
  // src/client.ts
2775
3359
  var DEFAULT_COLUMNS = "*";
2776
- var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
2777
3360
  var SAFE_CAST_PATTERN = /^[a-z_][a-z0-9_]*(?:\[\])?$/i;
2778
3361
  var ATHENA_NORMALIZED_ERROR_KEY = "__athenaNormalizedError";
3362
+ var QUERY_TRACE_STACK_SKIP_PATTERNS = [
3363
+ "src\\client.ts",
3364
+ "src/client.ts",
3365
+ "dist\\client.",
3366
+ "dist/client.",
3367
+ "node_modules\\@xylex-group\\athena",
3368
+ "node_modules/@xylex-group/athena",
3369
+ "node:internal",
3370
+ "internal/process"
3371
+ ];
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
+ }
2779
3384
  function formatResult(response) {
2780
3385
  const result = {
2781
3386
  data: response.data ?? null,
2782
- error: response.error ?? null,
3387
+ error: null,
2783
3388
  errorDetails: response.errorDetails ?? null,
2784
3389
  status: response.status,
3390
+ statusText: response.statusText ?? null,
2785
3391
  raw: response.raw
2786
3392
  };
2787
3393
  if (response.count !== void 0) {
@@ -2798,26 +3404,243 @@ function attachNormalizedError(result, normalizedError) {
2798
3404
  });
2799
3405
  }
2800
3406
  function createResultFormatter(experimental) {
2801
- if (!experimental?.enableErrorNormalization) {
2802
- return formatResult;
2803
- }
2804
3407
  return (response, context) => {
2805
3408
  const result = formatResult(response);
2806
- if (result.error == null) {
3409
+ if (response.error == null && response.errorDetails == null) {
2807
3410
  return result;
2808
3411
  }
2809
- const normalizedError = normalizeAthenaError(result, context);
3412
+ const normalizedError = normalizeAthenaError(
3413
+ {
3414
+ ...result,
3415
+ error: response.error ?? response.errorDetails?.message ?? null
3416
+ },
3417
+ context
3418
+ );
3419
+ result.error = createResultError(response, result, normalizedError);
2810
3420
  attachNormalizedError(result, normalizedError);
2811
3421
  return result;
2812
3422
  };
2813
3423
  }
2814
- function toSingleResult(response) {
2815
- const payload = response.data;
2816
- const singleData = Array.isArray(payload) ? payload.length ? payload[0] : null : payload ?? null;
2817
- return {
2818
- ...response,
2819
- data: singleData
2820
- };
3424
+ function isRecord6(value) {
3425
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
3426
+ }
3427
+ function firstNonEmptyString2(...values) {
3428
+ for (const value of values) {
3429
+ if (typeof value === "string" && value.trim().length > 0) {
3430
+ return value.trim();
3431
+ }
3432
+ }
3433
+ return void 0;
3434
+ }
3435
+ function resolveStructuredErrorPayload2(raw) {
3436
+ if (!isRecord6(raw)) return null;
3437
+ return isRecord6(raw.error) ? raw.error : raw;
3438
+ }
3439
+ function resolveStructuredErrorDetails(payload, message) {
3440
+ if (!payload || !("details" in payload)) {
3441
+ return null;
3442
+ }
3443
+ const details = payload.details;
3444
+ if (details == null) {
3445
+ return null;
3446
+ }
3447
+ if (typeof details === "string" && details.trim() === message.trim()) {
3448
+ return null;
3449
+ }
3450
+ return details;
3451
+ }
3452
+ function createResultError(response, result, normalized) {
3453
+ const rawRecord = isRecord6(response.raw) ? response.raw : null;
3454
+ const payload = resolveStructuredErrorPayload2(response.raw);
3455
+ const message = firstNonEmptyString2(
3456
+ response.error,
3457
+ payload?.message,
3458
+ payload?.error,
3459
+ payload?.details,
3460
+ response.errorDetails?.message,
3461
+ normalized.message
3462
+ ) ?? normalized.message;
3463
+ const statusText = firstNonEmptyString2(response.statusText, rawRecord?.statusText) ?? null;
3464
+ const hint = firstNonEmptyString2(payload?.hint, response.errorDetails?.hint) ?? null;
3465
+ const code = firstNonEmptyString2(payload?.code) ?? normalized.code;
3466
+ const details = resolveStructuredErrorDetails(payload, message) ?? response.errorDetails?.cause ?? null;
3467
+ return {
3468
+ message,
3469
+ code,
3470
+ athenaCode: normalized.code,
3471
+ gatewayCode: response.errorDetails?.code ?? null,
3472
+ kind: normalized.kind,
3473
+ category: normalized.category,
3474
+ retryable: normalized.retryable,
3475
+ details,
3476
+ hint,
3477
+ status: result.status,
3478
+ statusText,
3479
+ constraint: normalized.constraint,
3480
+ table: normalized.table,
3481
+ operation: normalized.operation,
3482
+ endpoint: response.errorDetails?.endpoint,
3483
+ method: response.errorDetails?.method,
3484
+ requestId: response.errorDetails?.requestId,
3485
+ cause: response.errorDetails?.cause,
3486
+ raw: result.raw
3487
+ };
3488
+ }
3489
+ function parseQueryTraceCallsiteFrame(frame) {
3490
+ const trimmed = frame.trim();
3491
+ if (!trimmed) {
3492
+ return null;
3493
+ }
3494
+ let body = trimmed.replace(/^at\s+/, "");
3495
+ if (body.startsWith("async ")) {
3496
+ body = body.slice(6);
3497
+ }
3498
+ let functionName;
3499
+ let location = body;
3500
+ const wrappedMatch = body.match(/^(.*?)\s+\((.*)\)$/);
3501
+ if (wrappedMatch) {
3502
+ functionName = wrappedMatch[1].trim() || void 0;
3503
+ location = wrappedMatch[2].trim();
3504
+ }
3505
+ const locationMatch = location.match(/^(.*):(\d+):(\d+)$/);
3506
+ if (!locationMatch) {
3507
+ return null;
3508
+ }
3509
+ const filePath = locationMatch[1].replace(/^file:\/\//, "");
3510
+ const line = Number(locationMatch[2]);
3511
+ const column = Number(locationMatch[3]);
3512
+ if (!Number.isFinite(line) || !Number.isFinite(column)) {
3513
+ return null;
3514
+ }
3515
+ const normalizedPath = filePath.replace(/\\/g, "/");
3516
+ const fileName = normalizedPath.split("/").at(-1) ?? filePath;
3517
+ return {
3518
+ filePath,
3519
+ fileName,
3520
+ line,
3521
+ column,
3522
+ frame: trimmed,
3523
+ functionName
3524
+ };
3525
+ }
3526
+ function captureQueryTraceCallsite() {
3527
+ const stack = new Error().stack;
3528
+ if (!stack) return null;
3529
+ const frames = stack.split("\n").slice(2).map((frame) => frame.trim()).filter(Boolean);
3530
+ for (const frame of frames) {
3531
+ if (QUERY_TRACE_STACK_SKIP_PATTERNS.some((pattern) => frame.includes(pattern))) {
3532
+ continue;
3533
+ }
3534
+ const callsite = parseQueryTraceCallsiteFrame(frame);
3535
+ if (callsite) return callsite;
3536
+ }
3537
+ const fallback = frames.find((frame) => !frame.includes("captureQueryTraceCallsite"));
3538
+ return fallback ? parseQueryTraceCallsiteFrame(fallback) : null;
3539
+ }
3540
+ function defaultQueryTraceLogger(event) {
3541
+ const target = event.table ?? event.functionName ?? "gateway";
3542
+ const outcomeState = event.outcome?.error ? "error" : "ok";
3543
+ const banner = `[athena-js][trace] ${event.operation.toUpperCase()} ${event.endpoint} ${target} ${event.durationMs}ms ${outcomeState}`;
3544
+ console.info(banner, event);
3545
+ }
3546
+ function captureTraceCallsite(tracer) {
3547
+ return tracer?.captureCallsite() ?? null;
3548
+ }
3549
+ function createTraceCallsiteStore(tracer, initialCallsite) {
3550
+ let storedCallsite = initialCallsite ?? void 0;
3551
+ return {
3552
+ resolve(callsite) {
3553
+ if (callsite) {
3554
+ storedCallsite = callsite;
3555
+ return callsite;
3556
+ }
3557
+ if (storedCallsite !== void 0) {
3558
+ return storedCallsite;
3559
+ }
3560
+ const capturedCallsite = captureTraceCallsite(tracer);
3561
+ if (capturedCallsite) {
3562
+ storedCallsite = capturedCallsite;
3563
+ }
3564
+ return capturedCallsite;
3565
+ }
3566
+ };
3567
+ }
3568
+ function createQueryTracer(experimental) {
3569
+ const traceOption = experimental?.traceQueries;
3570
+ if (!traceOption) {
3571
+ return void 0;
3572
+ }
3573
+ const logger = typeof traceOption === "object" && traceOption.logger ? traceOption.logger : defaultQueryTraceLogger;
3574
+ const emit = (event) => {
3575
+ try {
3576
+ logger(event);
3577
+ } catch (error) {
3578
+ console.warn("[athena-js][trace] logger failed", error);
3579
+ }
3580
+ };
3581
+ return {
3582
+ captureCallsite: captureQueryTraceCallsite,
3583
+ publishSuccess(context, result, durationMs, callsite) {
3584
+ emit({
3585
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3586
+ durationMs,
3587
+ operation: context.operation,
3588
+ endpoint: context.endpoint,
3589
+ table: context.table,
3590
+ functionName: context.functionName,
3591
+ sql: context.sql,
3592
+ payload: context.payload,
3593
+ options: context.options,
3594
+ callsite,
3595
+ outcome: {
3596
+ status: result.status,
3597
+ error: result.error,
3598
+ errorDetails: result.errorDetails ?? null,
3599
+ count: result.count ?? null,
3600
+ data: result.data,
3601
+ raw: result.raw
3602
+ }
3603
+ });
3604
+ },
3605
+ publishFailure(context, error, durationMs, callsite) {
3606
+ emit({
3607
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3608
+ durationMs,
3609
+ operation: context.operation,
3610
+ endpoint: context.endpoint,
3611
+ table: context.table,
3612
+ functionName: context.functionName,
3613
+ sql: context.sql,
3614
+ payload: context.payload,
3615
+ options: context.options,
3616
+ callsite,
3617
+ thrownError: error
3618
+ });
3619
+ }
3620
+ };
3621
+ }
3622
+ async function executeWithQueryTrace(tracer, context, runner, callsiteOverride) {
3623
+ if (!tracer) {
3624
+ return runner();
3625
+ }
3626
+ const callsite = callsiteOverride ?? tracer.captureCallsite();
3627
+ const startedAt = Date.now();
3628
+ try {
3629
+ const result = await runner();
3630
+ tracer.publishSuccess(context, result, Date.now() - startedAt, callsite);
3631
+ return result;
3632
+ } catch (error) {
3633
+ tracer.publishFailure(context, error, Date.now() - startedAt, callsite);
3634
+ throw error;
3635
+ }
3636
+ }
3637
+ function toSingleResult(response) {
3638
+ const payload = response.data;
3639
+ const singleData = Array.isArray(payload) ? payload.length ? payload[0] : null : payload ?? null;
3640
+ return {
3641
+ ...response,
3642
+ data: singleData
3643
+ };
2821
3644
  }
2822
3645
  function mergeOptions(...options) {
2823
3646
  return options.reduce((acc, next) => {
@@ -2831,15 +3654,16 @@ function asAthenaJsonObject(value) {
2831
3654
  function asAthenaJsonObjectArray(values) {
2832
3655
  return values;
2833
3656
  }
2834
- function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS) {
3657
+ function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS, tracer, initialCallsite) {
2835
3658
  let selectedColumns = defaultColumns === null ? void 0 : defaultColumns;
2836
3659
  let selectedOptions;
2837
3660
  let promise = null;
2838
- const run = (columns, options) => {
3661
+ const callsiteStore = createTraceCallsiteStore(tracer, initialCallsite);
3662
+ const run = (columns, options, callsite) => {
2839
3663
  const payloadColumns = columns ?? selectedColumns;
2840
3664
  const payloadOptions = options ?? selectedOptions;
2841
3665
  if (!promise) {
2842
- promise = executor(payloadColumns, payloadOptions);
3666
+ promise = executor(payloadColumns, payloadOptions, callsiteStore.resolve(callsite));
2843
3667
  }
2844
3668
  return promise;
2845
3669
  };
@@ -2847,7 +3671,7 @@ function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS) {
2847
3671
  select(columns = selectedColumns, options) {
2848
3672
  selectedColumns = columns;
2849
3673
  selectedOptions = options ?? selectedOptions;
2850
- return run(columns, options);
3674
+ return run(columns, options, captureTraceCallsite(tracer));
2851
3675
  },
2852
3676
  returning(columns = selectedColumns, options) {
2853
3677
  return mutationQuery.select(columns, options);
@@ -2855,7 +3679,7 @@ function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS) {
2855
3679
  single(columns = selectedColumns, options) {
2856
3680
  selectedColumns = columns;
2857
3681
  selectedOptions = options ?? selectedOptions;
2858
- return run(columns, options).then(toSingleResult);
3682
+ return run(columns, options, captureTraceCallsite(tracer)).then(toSingleResult);
2859
3683
  },
2860
3684
  maybeSingle(columns = selectedColumns, options) {
2861
3685
  return mutationQuery.single(columns, options);
@@ -2878,21 +3702,12 @@ function getResourceId(state) {
2878
3702
  );
2879
3703
  return candidate?.value?.toString();
2880
3704
  }
2881
- function stringifyFilterValue(value) {
3705
+ function stringifyFilterValue2(value) {
2882
3706
  if (Array.isArray(value)) {
2883
3707
  return value.join(",");
2884
3708
  }
2885
3709
  return String(value);
2886
3710
  }
2887
- function isUuidString(value) {
2888
- return UUID_PATTERN.test(value.trim());
2889
- }
2890
- function isUuidIdentifierColumn(column) {
2891
- return column === "id" || /(?:^|_)uuid(?:_|$)/i.test(column) || /_id$/i.test(column);
2892
- }
2893
- function shouldUseUuidTextComparison(column, value) {
2894
- return typeof value === "string" && isUuidString(value) && isUuidIdentifierColumn(column);
2895
- }
2896
3711
  function normalizeCast(cast) {
2897
3712
  const normalized = cast.trim().toLowerCase();
2898
3713
  if (!SAFE_CAST_PATTERN.test(normalized)) {
@@ -2915,25 +3730,92 @@ function withCast(expression, cast) {
2915
3730
  }
2916
3731
  function buildSelectColumnsClause(columns) {
2917
3732
  if (Array.isArray(columns)) {
2918
- return columns.map((column) => quoteQualifiedIdentifier(column)).join(", ");
3733
+ return columns.map((column) => quoteSelectColumnToken(column)).join(", ");
2919
3734
  }
2920
3735
  return quoteSelectColumnsExpression(columns);
2921
3736
  }
3737
+ function parseIdentifierSegment(input) {
3738
+ const trimmed = input.trim();
3739
+ if (!trimmed) return null;
3740
+ if (!trimmed.startsWith('"')) {
3741
+ return {
3742
+ normalizedValue: trimmed.toLowerCase()
3743
+ };
3744
+ }
3745
+ let value = "";
3746
+ let index = 1;
3747
+ let closed = false;
3748
+ while (index < trimmed.length) {
3749
+ const char = trimmed[index];
3750
+ const next = index + 1 < trimmed.length ? trimmed[index + 1] : "";
3751
+ if (char === '"' && next === '"') {
3752
+ value += '"';
3753
+ index += 2;
3754
+ continue;
3755
+ }
3756
+ if (char === '"') {
3757
+ closed = true;
3758
+ index += 1;
3759
+ break;
3760
+ }
3761
+ value += char;
3762
+ index += 1;
3763
+ }
3764
+ if (!closed || trimmed.slice(index).trim().length > 0 || !value.trim()) {
3765
+ return null;
3766
+ }
3767
+ return {
3768
+ normalizedValue: value
3769
+ };
3770
+ }
3771
+ function splitQualifiedTableName(tableName) {
3772
+ const trimmed = tableName.trim();
3773
+ let inQuotes = false;
3774
+ for (let index = 0; index < trimmed.length; index += 1) {
3775
+ const char = trimmed[index];
3776
+ const next = index + 1 < trimmed.length ? trimmed[index + 1] : "";
3777
+ if (char === '"') {
3778
+ if (inQuotes && next === '"') {
3779
+ index += 1;
3780
+ continue;
3781
+ }
3782
+ inQuotes = !inQuotes;
3783
+ continue;
3784
+ }
3785
+ if (char === "." && !inQuotes) {
3786
+ const schemaSegment = trimmed.slice(0, index).trim();
3787
+ const tableSegment = trimmed.slice(index + 1).trim();
3788
+ if (!schemaSegment || !tableSegment) {
3789
+ return null;
3790
+ }
3791
+ return { schemaSegment };
3792
+ }
3793
+ }
3794
+ return null;
3795
+ }
2922
3796
  function resolveTableNameForCall(tableName, schema) {
2923
3797
  if (!schema) return tableName;
2924
3798
  const normalizedSchema = schema.trim();
2925
3799
  if (!normalizedSchema) {
2926
3800
  throw new Error("schema option must be a non-empty string");
2927
3801
  }
2928
- if (tableName.includes(".")) {
2929
- if (tableName.startsWith(`${normalizedSchema}.`)) {
2930
- return tableName;
3802
+ const normalizedTableName = tableName.trim();
3803
+ const parsedSchema = parseIdentifierSegment(normalizedSchema);
3804
+ if (!parsedSchema) {
3805
+ throw new Error("schema option must be a non-empty string");
3806
+ }
3807
+ const qualified = splitQualifiedTableName(normalizedTableName);
3808
+ if (qualified) {
3809
+ const parsedTableSchema = parseIdentifierSegment(qualified.schemaSegment);
3810
+ const sameSchema = parsedTableSchema ? parsedTableSchema.normalizedValue === parsedSchema.normalizedValue : normalizedTableName.startsWith(`${normalizedSchema}.`);
3811
+ if (sameSchema) {
3812
+ return normalizedTableName;
2931
3813
  }
2932
3814
  throw new Error(
2933
- `schema option "${normalizedSchema}" conflicts with schema-qualified table "${tableName}"`
3815
+ `schema option "${normalizedSchema}" conflicts with schema-qualified table "${normalizedTableName}"`
2934
3816
  );
2935
3817
  }
2936
- return `${normalizedSchema}.${tableName}`;
3818
+ return `${normalizedSchema}.${normalizedTableName}`;
2937
3819
  }
2938
3820
  function conditionToSqlClause(condition) {
2939
3821
  if (!condition.column) return null;
@@ -3011,6 +3893,237 @@ function buildTypedSelectQuery(input) {
3011
3893
  }
3012
3894
  return `${sqlParts.join(" ")};`;
3013
3895
  }
3896
+ function sanitizeSqlComment(comment) {
3897
+ return comment.replace(/\*\//g, "* /");
3898
+ }
3899
+ function toSqlJsonLiteral(value) {
3900
+ if (value === void 0) return "DEFAULT";
3901
+ if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
3902
+ return toSqlLiteral(value);
3903
+ }
3904
+ return `'${escapeSqlStringLiteral(JSON.stringify(value))}'::jsonb`;
3905
+ }
3906
+ function conditionToDebugSqlClause(condition) {
3907
+ const exact = conditionToSqlClause(condition);
3908
+ if (exact) return exact;
3909
+ const rawCondition = sanitizeSqlComment(JSON.stringify(condition));
3910
+ if (!condition.column) {
3911
+ return `TRUE /* unsupported condition: ${rawCondition} */`;
3912
+ }
3913
+ const column = withCast(quoteQualifiedIdentifier(condition.column), condition.column_cast);
3914
+ const value = condition.value;
3915
+ const rhs = withCast(toSqlJsonLiteral(value), condition.value_cast);
3916
+ switch (condition.operator) {
3917
+ case "contains":
3918
+ return `${column} @> ${rhs}`;
3919
+ case "containedBy":
3920
+ return `${column} <@ ${rhs}`;
3921
+ case "not":
3922
+ return `TRUE /* NOT expression passthrough: ${rawCondition} */`;
3923
+ case "or":
3924
+ return `TRUE /* OR expression passthrough: ${rawCondition} */`;
3925
+ default:
3926
+ return `TRUE /* unsupported condition: ${rawCondition} */`;
3927
+ }
3928
+ }
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
+ function appendOrderLimitOffset(sqlParts, order, limit, offset) {
3941
+ if (order?.field) {
3942
+ const direction = order.direction === "descending" ? "DESC" : "ASC";
3943
+ sqlParts.push(`ORDER BY ${quoteQualifiedIdentifier(order.field)} ${direction}`);
3944
+ }
3945
+ if (limit !== void 0) {
3946
+ sqlParts.push(`LIMIT ${Math.max(0, Math.trunc(limit))}`);
3947
+ }
3948
+ if (offset !== void 0) {
3949
+ sqlParts.push(`OFFSET ${Math.max(0, Math.trunc(offset))}`);
3950
+ }
3951
+ }
3952
+ function buildDebugSelectQuery(input) {
3953
+ const sqlParts = [
3954
+ `SELECT ${buildSelectColumnsClause(input.columns)} FROM ${quoteQualifiedIdentifier(input.tableName)}`
3955
+ ];
3956
+ if (input.conditions?.length) {
3957
+ const whereClauses = input.conditions.map(conditionToDebugSqlClause);
3958
+ sqlParts.push(`WHERE ${whereClauses.join(" AND ")}`);
3959
+ }
3960
+ const pagination = resolvePagination(input);
3961
+ appendOrderLimitOffset(sqlParts, input.order, pagination.limit, pagination.offset);
3962
+ return `${sqlParts.join(" ")};`;
3963
+ }
3964
+ function resolveDebugTableIdentifier(tableName) {
3965
+ if (!tableName?.trim()) {
3966
+ return '"__unknown_table__"';
3967
+ }
3968
+ return quoteQualifiedIdentifier(tableName);
3969
+ }
3970
+ function buildInsertDebugSql(payload) {
3971
+ const rows = Array.isArray(payload.insert_body) ? payload.insert_body : [payload.insert_body];
3972
+ const columns = [];
3973
+ const seen = /* @__PURE__ */ new Set();
3974
+ for (const row of rows) {
3975
+ for (const column of Object.keys(row)) {
3976
+ if (seen.has(column)) continue;
3977
+ seen.add(column);
3978
+ columns.push(column);
3979
+ }
3980
+ }
3981
+ const sqlParts = [`INSERT INTO ${quoteQualifiedIdentifier(payload.table_name)}`];
3982
+ if (!rows.length || !columns.length) {
3983
+ sqlParts.push("DEFAULT VALUES");
3984
+ if (rows.length > 1) {
3985
+ sqlParts.push(`/* trace: ${rows.length} rows collapsed to DEFAULT VALUES */`);
3986
+ }
3987
+ } else {
3988
+ const valuesClause = rows.map((row) => {
3989
+ const values = columns.map((column) => {
3990
+ const hasColumn = Object.prototype.hasOwnProperty.call(row, column);
3991
+ if (!hasColumn) {
3992
+ return payload.default_to_null ? "NULL" : "DEFAULT";
3993
+ }
3994
+ const rowValue = row[column];
3995
+ return toSqlJsonLiteral(rowValue);
3996
+ });
3997
+ return `(${values.join(", ")})`;
3998
+ }).join(", ");
3999
+ const columnClause = columns.map((column) => quoteQualifiedIdentifier(column)).join(", ");
4000
+ sqlParts.push(`(${columnClause})`);
4001
+ sqlParts.push(`VALUES ${valuesClause}`);
4002
+ }
4003
+ if (payload.on_conflict) {
4004
+ const conflictColumns = Array.isArray(payload.on_conflict) ? payload.on_conflict.map((column) => quoteQualifiedIdentifier(column)).join(", ") : payload.on_conflict;
4005
+ if (payload.update_body && Object.keys(payload.update_body).length > 0) {
4006
+ const assignments = Object.entries(payload.update_body).map(
4007
+ ([column, value]) => `${quoteQualifiedIdentifier(column)} = ${toSqlJsonLiteral(value)}`
4008
+ );
4009
+ sqlParts.push(`ON CONFLICT (${conflictColumns}) DO UPDATE SET ${assignments.join(", ")}`);
4010
+ } else {
4011
+ sqlParts.push(`ON CONFLICT (${conflictColumns}) DO NOTHING`);
4012
+ }
4013
+ }
4014
+ if (payload.columns) {
4015
+ sqlParts.push(`RETURNING ${buildSelectColumnsClause(payload.columns)}`);
4016
+ }
4017
+ return `${sqlParts.join(" ")};`;
4018
+ }
4019
+ function buildUpdateDebugSql(payload) {
4020
+ const set = payload.set ?? payload.data ?? {};
4021
+ const assignments = Object.entries(set).map(
4022
+ ([column, value]) => `${quoteQualifiedIdentifier(column)} = ${toSqlJsonLiteral(value)}`
4023
+ );
4024
+ const sqlParts = [
4025
+ `UPDATE ${resolveDebugTableIdentifier(payload.table_name)} SET ${assignments.length ? assignments.join(", ") : "/* empty set */"}`
4026
+ ];
4027
+ if (payload.conditions?.length) {
4028
+ const whereClauses = payload.conditions.map(conditionToDebugSqlClause);
4029
+ sqlParts.push(`WHERE ${whereClauses.join(" AND ")}`);
4030
+ }
4031
+ const pagination = resolvePagination({
4032
+ currentPage: payload.current_page,
4033
+ pageSize: payload.page_size
4034
+ });
4035
+ appendOrderLimitOffset(sqlParts, payload.sort_by, pagination.limit, pagination.offset);
4036
+ if (payload.columns) {
4037
+ sqlParts.push(`RETURNING ${buildSelectColumnsClause(payload.columns)}`);
4038
+ }
4039
+ return `${sqlParts.join(" ")};`;
4040
+ }
4041
+ function buildDeleteDebugSql(payload) {
4042
+ const sqlParts = [`DELETE FROM ${quoteQualifiedIdentifier(payload.table_name)}`];
4043
+ const whereClauses = [];
4044
+ if (payload.resource_id) {
4045
+ whereClauses.push(`"resource_id" = ${toSqlLiteral(payload.resource_id)}`);
4046
+ }
4047
+ if (payload.conditions?.length) {
4048
+ whereClauses.push(...payload.conditions.map(conditionToDebugSqlClause));
4049
+ }
4050
+ if (whereClauses.length) {
4051
+ sqlParts.push(`WHERE ${whereClauses.join(" AND ")}`);
4052
+ }
4053
+ const pagination = resolvePagination({
4054
+ currentPage: payload.current_page,
4055
+ pageSize: payload.page_size
4056
+ });
4057
+ appendOrderLimitOffset(sqlParts, payload.sort_by, pagination.limit, pagination.offset);
4058
+ if (payload.columns) {
4059
+ sqlParts.push(`RETURNING ${buildSelectColumnsClause(payload.columns)}`);
4060
+ }
4061
+ return `${sqlParts.join(" ")};`;
4062
+ }
4063
+ function rpcFilterToSqlClause(filter) {
4064
+ const column = quoteQualifiedIdentifier(filter.column);
4065
+ const value = filter.value;
4066
+ switch (filter.operator) {
4067
+ case "eq":
4068
+ case "neq":
4069
+ case "gt":
4070
+ case "gte":
4071
+ case "lt":
4072
+ case "lte":
4073
+ case "like":
4074
+ case "ilike": {
4075
+ if (value === void 0 || Array.isArray(value)) {
4076
+ return `TRUE /* unsupported rpc filter: ${sanitizeSqlComment(JSON.stringify(filter))} */`;
4077
+ }
4078
+ const operatorMap = {
4079
+ eq: "=",
4080
+ neq: "!=",
4081
+ gt: ">",
4082
+ gte: ">=",
4083
+ lt: "<",
4084
+ lte: "<=",
4085
+ like: "LIKE",
4086
+ ilike: "ILIKE"
4087
+ };
4088
+ return `${column} ${operatorMap[filter.operator]} ${toSqlLiteral(value)}`;
4089
+ }
4090
+ case "is":
4091
+ if (value === null) return `${column} IS NULL`;
4092
+ if (value === true) return `${column} IS TRUE`;
4093
+ if (value === false) return `${column} IS FALSE`;
4094
+ return `TRUE /* unsupported rpc filter: ${sanitizeSqlComment(JSON.stringify(filter))} */`;
4095
+ case "in":
4096
+ if (!Array.isArray(value)) {
4097
+ return `TRUE /* unsupported rpc filter: ${sanitizeSqlComment(JSON.stringify(filter))} */`;
4098
+ }
4099
+ if (value.length === 0) return "FALSE";
4100
+ return `${column} IN (${value.map((item) => toSqlLiteral(item)).join(", ")})`;
4101
+ default:
4102
+ return `TRUE /* unsupported rpc filter: ${sanitizeSqlComment(JSON.stringify(filter))} */`;
4103
+ }
4104
+ }
4105
+ function buildRpcDebugSql(payload) {
4106
+ const argsEntries = payload.args ? Object.entries(payload.args) : [];
4107
+ const argsClause = argsEntries.map(([key, value]) => `${quoteQualifiedIdentifier(key)} => ${toSqlJsonLiteral(value)}`).join(", ");
4108
+ const functionRef = payload.schema ? `${quoteQualifiedIdentifier(payload.schema)}.${quoteQualifiedIdentifier(payload.function)}` : quoteQualifiedIdentifier(payload.function);
4109
+ const sqlParts = [
4110
+ `SELECT ${payload.select ? quoteSelectColumnsExpression(payload.select) : "*"} FROM ${functionRef}(${argsClause})`
4111
+ ];
4112
+ if (payload.filters?.length) {
4113
+ sqlParts.push(`WHERE ${payload.filters.map(rpcFilterToSqlClause).join(" AND ")}`);
4114
+ }
4115
+ if (payload.order?.column) {
4116
+ const direction = payload.order.ascending === false ? "DESC" : "ASC";
4117
+ sqlParts.push(`ORDER BY ${quoteQualifiedIdentifier(payload.order.column)} ${direction}`);
4118
+ }
4119
+ if (payload.limit !== void 0) {
4120
+ sqlParts.push(`LIMIT ${Math.max(0, Math.trunc(payload.limit))}`);
4121
+ }
4122
+ if (payload.offset !== void 0) {
4123
+ sqlParts.push(`OFFSET ${Math.max(0, Math.trunc(payload.offset))}`);
4124
+ }
4125
+ return `${sqlParts.join(" ")};`;
4126
+ }
3014
4127
  function createFilterMethods(state, addCondition, self) {
3015
4128
  return {
3016
4129
  eq(column, value) {
@@ -3122,7 +4235,7 @@ function createFilterMethods(state, addCondition, self) {
3122
4235
  not(columnOrExpression, operator, value) {
3123
4236
  const expression = String(columnOrExpression);
3124
4237
  if (operator != null && value !== void 0) {
3125
- addCondition("not", void 0, `${expression}.${operator}.${stringifyFilterValue(value)}`);
4238
+ addCondition("not", void 0, `${expression}.${operator}.${stringifyFilterValue2(value)}`);
3126
4239
  } else {
3127
4240
  addCondition("not", void 0, expression);
3128
4241
  }
@@ -3185,14 +4298,15 @@ function createRpcFilterMethods(filters, self) {
3185
4298
  }
3186
4299
  };
3187
4300
  }
3188
- function createRpcBuilder(functionName, args, baseOptions, client, formatGatewayResult) {
4301
+ function createRpcBuilder(functionName, args, baseOptions, client, formatGatewayResult, tracer, initialCallsite) {
3189
4302
  const state = {
3190
4303
  filters: []
3191
4304
  };
3192
4305
  let selectedColumns;
3193
4306
  let selectedOptions;
3194
4307
  let promise = null;
3195
- const executeRpc = async (columns, options) => {
4308
+ const callsiteStore = createTraceCallsiteStore(tracer, initialCallsite);
4309
+ const executeRpc = async (columns, options, callsite) => {
3196
4310
  const mergedOptions = mergeOptions(baseOptions, options);
3197
4311
  const payload = {
3198
4312
  function: functionName,
@@ -3206,14 +4320,30 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
3206
4320
  offset: state.offset,
3207
4321
  order: state.order
3208
4322
  };
3209
- const response = await client.rpcGateway(payload, mergedOptions);
3210
- return formatGatewayResult(response, { operation: "rpc" });
4323
+ const endpoint = mergedOptions?.get ? `/rpc/${functionName}` : "/gateway/rpc";
4324
+ const sql = buildRpcDebugSql(payload);
4325
+ return executeWithQueryTrace(
4326
+ tracer,
4327
+ {
4328
+ operation: "rpc",
4329
+ endpoint,
4330
+ functionName,
4331
+ sql,
4332
+ payload,
4333
+ options: mergedOptions
4334
+ },
4335
+ async () => {
4336
+ const response = await client.rpcGateway(payload, mergedOptions);
4337
+ return formatGatewayResult(response, { operation: "rpc" });
4338
+ },
4339
+ callsite
4340
+ );
3211
4341
  };
3212
- const run = (columns, options) => {
4342
+ const run = (columns, options, callsite) => {
3213
4343
  const payloadColumns = columns ?? selectedColumns;
3214
4344
  const payloadOptions = options ?? selectedOptions;
3215
4345
  if (!promise) {
3216
- promise = executeRpc(payloadColumns, payloadOptions);
4346
+ promise = executeRpc(payloadColumns, payloadOptions, callsiteStore.resolve(callsite));
3217
4347
  }
3218
4348
  return promise;
3219
4349
  };
@@ -3223,10 +4353,10 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
3223
4353
  select(columns = selectedColumns, options) {
3224
4354
  selectedColumns = columns;
3225
4355
  selectedOptions = options ?? selectedOptions;
3226
- return run(columns, options);
4356
+ return run(columns, options, captureTraceCallsite(tracer));
3227
4357
  },
3228
4358
  async single(columns, options) {
3229
- const result = await run(columns, options);
4359
+ const result = await run(columns, options, captureTraceCallsite(tracer));
3230
4360
  return toSingleResult(result);
3231
4361
  },
3232
4362
  maybeSingle(columns, options) {
@@ -3261,7 +4391,7 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
3261
4391
  });
3262
4392
  return builder;
3263
4393
  }
3264
- function createTableBuilder(tableName, client, formatGatewayResult) {
4394
+ function createTableBuilder(tableName, client, formatGatewayResult, tracer, experimental) {
3265
4395
  const state = {
3266
4396
  conditions: []
3267
4397
  };
@@ -3293,15 +4423,24 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
3293
4423
  }
3294
4424
  state.conditions.push(condition);
3295
4425
  };
4426
+ const snapshotState = () => ({
4427
+ conditions: state.conditions.map((condition) => ({ ...condition })),
4428
+ limit: state.limit,
4429
+ offset: state.offset,
4430
+ order: state.order ? { ...state.order } : void 0,
4431
+ currentPage: state.currentPage,
4432
+ pageSize: state.pageSize,
4433
+ totalPages: state.totalPages
4434
+ });
3296
4435
  const builder = {};
3297
4436
  const filterMethods = createFilterMethods(
3298
4437
  state,
3299
4438
  addCondition,
3300
4439
  builder
3301
4440
  );
3302
- const runSelect = async (columns = DEFAULT_COLUMNS, options) => {
4441
+ const runSelect = async (columns = DEFAULT_COLUMNS, options, executionState = snapshotState(), callsite) => {
3303
4442
  const resolvedTableName = resolveTableNameForCall(tableName, options?.schema);
3304
- const conditions = state.conditions.length ? state.conditions.map((condition) => ({ ...condition })) : void 0;
4443
+ const conditions = executionState.conditions.length ? executionState.conditions.map((condition) => ({ ...condition })) : void 0;
3305
4444
  const hasTypedEqualityComparison = conditions?.some(
3306
4445
  (condition) => condition.operator === "eq" && (condition.value_cast !== void 0 || condition.column_cast !== void 0)
3307
4446
  ) ?? false;
@@ -3310,53 +4449,107 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
3310
4449
  tableName: resolvedTableName,
3311
4450
  columns,
3312
4451
  conditions,
3313
- limit: state.limit,
3314
- offset: state.offset,
3315
- currentPage: state.currentPage,
3316
- pageSize: state.pageSize,
3317
- order: state.order
4452
+ limit: executionState.limit,
4453
+ offset: executionState.offset,
4454
+ currentPage: executionState.currentPage,
4455
+ pageSize: executionState.pageSize,
4456
+ order: executionState.order
3318
4457
  });
3319
4458
  if (query) {
3320
- const queryResponse = await client.queryGateway({ query }, options);
3321
- return formatGatewayResult(queryResponse, { table: resolvedTableName, operation: "select" });
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
+ );
3322
4476
  }
3323
4477
  }
3324
4478
  const payload = {
3325
4479
  table_name: resolvedTableName,
3326
4480
  columns,
3327
4481
  conditions,
3328
- limit: state.limit,
3329
- offset: state.offset,
3330
- current_page: state.currentPage,
3331
- page_size: state.pageSize,
3332
- total_pages: state.totalPages,
3333
- sort_by: state.order,
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,
3334
4488
  strip_nulls: options?.stripNulls ?? true,
3335
4489
  count: options?.count,
3336
4490
  head: options?.head
3337
4491
  };
3338
- const response = await client.fetchGateway(payload, options);
3339
- return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
4492
+ const sql = buildDebugSelectQuery({
4493
+ 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
4501
+ });
4502
+ return executeWithQueryTrace(
4503
+ tracer,
4504
+ {
4505
+ operation: "select",
4506
+ endpoint: "/gateway/fetch",
4507
+ table: resolvedTableName,
4508
+ sql,
4509
+ payload,
4510
+ options
4511
+ },
4512
+ async () => {
4513
+ const response = await client.fetchGateway(payload, options);
4514
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
4515
+ },
4516
+ callsite
4517
+ );
3340
4518
  };
3341
- const createSelectChain = (columns, options) => {
4519
+ const createSelectChain = (columns, options, initialCallsite) => {
3342
4520
  const chain = {};
4521
+ const callsiteStore = createTraceCallsiteStore(tracer, initialCallsite);
3343
4522
  const filterMethods2 = createFilterMethods(state, addCondition, chain);
3344
4523
  Object.assign(chain, filterMethods2, {
3345
4524
  async single(cols, opts) {
3346
- const r = await runSelect(cols ?? columns, opts ?? options);
4525
+ const r = await runSelect(
4526
+ cols ?? columns,
4527
+ opts ?? options,
4528
+ snapshotState(),
4529
+ callsiteStore.resolve(captureTraceCallsite(tracer))
4530
+ );
3347
4531
  return toSingleResult(r);
3348
4532
  },
3349
4533
  maybeSingle(cols, opts) {
3350
4534
  return chain.single(cols, opts);
3351
4535
  },
3352
4536
  then(onfulfilled, onrejected) {
3353
- return runSelect(columns, options).then(onfulfilled, onrejected);
4537
+ return runSelect(
4538
+ columns,
4539
+ options,
4540
+ snapshotState(),
4541
+ callsiteStore.resolve()
4542
+ ).then(onfulfilled, onrejected);
3354
4543
  },
3355
4544
  catch(onrejected) {
3356
- return runSelect(columns, options).catch(onrejected);
4545
+ return runSelect(columns, options, snapshotState(), callsiteStore.resolve()).catch(
4546
+ onrejected
4547
+ );
3357
4548
  },
3358
4549
  finally(onfinally) {
3359
- return runSelect(columns, options).finally(onfinally);
4550
+ return runSelect(columns, options, snapshotState(), callsiteStore.resolve()).finally(
4551
+ onfinally
4552
+ );
3360
4553
  }
3361
4554
  });
3362
4555
  return chain;
@@ -3373,11 +4566,75 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
3373
4566
  return builder;
3374
4567
  },
3375
4568
  select(columns = DEFAULT_COLUMNS, options) {
3376
- return createSelectChain(columns, options);
4569
+ return createSelectChain(columns, options, captureTraceCallsite(tracer));
4570
+ },
4571
+ async findMany(options) {
4572
+ const columns = compileSelectShape(options.select);
4573
+ const baseState = snapshotState();
4574
+ const executionState = snapshotState();
4575
+ const callsite = captureTraceCallsite(tracer);
4576
+ const compiledWhere = compileWhere(options.where);
4577
+ if (compiledWhere?.length) {
4578
+ executionState.conditions.push(...compiledWhere);
4579
+ }
4580
+ if (options.orderBy !== void 0) {
4581
+ executionState.order = compileOrderBy(options.orderBy);
4582
+ }
4583
+ if (options.limit !== void 0) {
4584
+ executionState.limit = options.limit;
4585
+ }
4586
+ if (experimental?.findManyAst && canUseFindManyAstTransport(baseState)) {
4587
+ const resolvedTableName = resolveTableNameForCall(tableName, void 0);
4588
+ const payload = {
4589
+ table_name: resolvedTableName,
4590
+ select: options.select
4591
+ };
4592
+ if (options.where !== void 0) {
4593
+ payload.where = options.where;
4594
+ }
4595
+ const astOrder = toFindManyAstOrder(executionState.order);
4596
+ if (astOrder !== void 0) {
4597
+ payload.orderBy = astOrder;
4598
+ }
4599
+ if (executionState.limit !== void 0) {
4600
+ payload.limit = executionState.limit;
4601
+ }
4602
+ const sql = buildDebugSelectQuery({
4603
+ tableName: resolvedTableName,
4604
+ columns,
4605
+ conditions: executionState.conditions,
4606
+ limit: executionState.limit,
4607
+ order: executionState.order
4608
+ });
4609
+ return executeWithQueryTrace(
4610
+ tracer,
4611
+ {
4612
+ operation: "select",
4613
+ endpoint: "/gateway/fetch",
4614
+ table: resolvedTableName,
4615
+ sql,
4616
+ payload
4617
+ },
4618
+ async () => {
4619
+ const response = await client.fetchGateway(
4620
+ payload
4621
+ );
4622
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
4623
+ },
4624
+ callsite
4625
+ );
4626
+ }
4627
+ return runSelect(
4628
+ columns,
4629
+ void 0,
4630
+ executionState,
4631
+ callsite
4632
+ );
3377
4633
  },
3378
4634
  insert(values, options) {
4635
+ const mutationCallsite = captureTraceCallsite(tracer);
3379
4636
  if (Array.isArray(values)) {
3380
- const executeInsertMany = async (columns, selectOptions) => {
4637
+ const executeInsertMany = async (columns, selectOptions, callsite) => {
3381
4638
  const mergedOptions = mergeOptions(options, selectOptions);
3382
4639
  const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
3383
4640
  const payload = {
@@ -3390,12 +4647,27 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
3390
4647
  if (mergedOptions?.defaultToNull !== void 0) {
3391
4648
  payload.default_to_null = mergedOptions.defaultToNull;
3392
4649
  }
3393
- const response = await client.insertGateway(payload, mergedOptions);
3394
- return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
4650
+ const sql = buildInsertDebugSql(payload);
4651
+ return executeWithQueryTrace(
4652
+ tracer,
4653
+ {
4654
+ operation: "insert",
4655
+ endpoint: "/gateway/insert",
4656
+ table: resolvedTableName,
4657
+ sql,
4658
+ payload,
4659
+ options: mergedOptions
4660
+ },
4661
+ async () => {
4662
+ const response = await client.insertGateway(payload, mergedOptions);
4663
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
4664
+ },
4665
+ callsite
4666
+ );
3395
4667
  };
3396
- return createMutationQuery(executeInsertMany);
4668
+ return createMutationQuery(executeInsertMany, DEFAULT_COLUMNS, tracer, mutationCallsite);
3397
4669
  }
3398
- const executeInsertOne = async (columns, selectOptions) => {
4670
+ const executeInsertOne = async (columns, selectOptions, callsite) => {
3399
4671
  const mergedOptions = mergeOptions(options, selectOptions);
3400
4672
  const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
3401
4673
  const payload = {
@@ -3408,14 +4680,30 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
3408
4680
  if (mergedOptions?.defaultToNull !== void 0) {
3409
4681
  payload.default_to_null = mergedOptions.defaultToNull;
3410
4682
  }
3411
- const response = await client.insertGateway(payload, mergedOptions);
3412
- return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
4683
+ const sql = buildInsertDebugSql(payload);
4684
+ return executeWithQueryTrace(
4685
+ tracer,
4686
+ {
4687
+ operation: "insert",
4688
+ endpoint: "/gateway/insert",
4689
+ table: resolvedTableName,
4690
+ sql,
4691
+ payload,
4692
+ options: mergedOptions
4693
+ },
4694
+ async () => {
4695
+ const response = await client.insertGateway(payload, mergedOptions);
4696
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
4697
+ },
4698
+ callsite
4699
+ );
3413
4700
  };
3414
- return createMutationQuery(executeInsertOne);
4701
+ return createMutationQuery(executeInsertOne, DEFAULT_COLUMNS, tracer, mutationCallsite);
3415
4702
  },
3416
4703
  upsert(values, options) {
4704
+ const mutationCallsite = captureTraceCallsite(tracer);
3417
4705
  if (Array.isArray(values)) {
3418
- const executeUpsertMany = async (columns, selectOptions) => {
4706
+ const executeUpsertMany = async (columns, selectOptions, callsite) => {
3419
4707
  const mergedOptions = mergeOptions(options, selectOptions);
3420
4708
  const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
3421
4709
  const payload = {
@@ -3430,12 +4718,27 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
3430
4718
  if (mergedOptions?.defaultToNull !== void 0) {
3431
4719
  payload.default_to_null = mergedOptions.defaultToNull;
3432
4720
  }
3433
- const response = await client.insertGateway(payload, mergedOptions);
3434
- return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
4721
+ const sql = buildInsertDebugSql(payload);
4722
+ return executeWithQueryTrace(
4723
+ tracer,
4724
+ {
4725
+ operation: "upsert",
4726
+ endpoint: "/gateway/insert",
4727
+ table: resolvedTableName,
4728
+ sql,
4729
+ payload,
4730
+ options: mergedOptions
4731
+ },
4732
+ async () => {
4733
+ const response = await client.insertGateway(payload, mergedOptions);
4734
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
4735
+ },
4736
+ callsite
4737
+ );
3435
4738
  };
3436
- return createMutationQuery(executeUpsertMany);
4739
+ return createMutationQuery(executeUpsertMany, DEFAULT_COLUMNS, tracer, mutationCallsite);
3437
4740
  }
3438
- const executeUpsertOne = async (columns, selectOptions) => {
4741
+ const executeUpsertOne = async (columns, selectOptions, callsite) => {
3439
4742
  const mergedOptions = mergeOptions(options, selectOptions);
3440
4743
  const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
3441
4744
  const payload = {
@@ -3450,13 +4753,29 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
3450
4753
  if (mergedOptions?.defaultToNull !== void 0) {
3451
4754
  payload.default_to_null = mergedOptions.defaultToNull;
3452
4755
  }
3453
- const response = await client.insertGateway(payload, mergedOptions);
3454
- return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
4756
+ const sql = buildInsertDebugSql(payload);
4757
+ return executeWithQueryTrace(
4758
+ tracer,
4759
+ {
4760
+ operation: "upsert",
4761
+ endpoint: "/gateway/insert",
4762
+ table: resolvedTableName,
4763
+ sql,
4764
+ payload,
4765
+ options: mergedOptions
4766
+ },
4767
+ async () => {
4768
+ const response = await client.insertGateway(payload, mergedOptions);
4769
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
4770
+ },
4771
+ callsite
4772
+ );
3455
4773
  };
3456
- return createMutationQuery(executeUpsertOne);
4774
+ return createMutationQuery(executeUpsertOne, DEFAULT_COLUMNS, tracer, mutationCallsite);
3457
4775
  },
3458
4776
  update(values, options) {
3459
- const executeUpdate = async (columns, selectOptions) => {
4777
+ const mutationCallsite = captureTraceCallsite(tracer);
4778
+ const executeUpdate = async (columns, selectOptions, callsite) => {
3460
4779
  const filters = state.conditions.length ? [...state.conditions] : void 0;
3461
4780
  const mergedOptions = mergeOptions(options, selectOptions);
3462
4781
  const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
@@ -3471,10 +4790,25 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
3471
4790
  if (state.pageSize !== void 0) payload.page_size = state.pageSize;
3472
4791
  if (state.totalPages !== void 0) payload.total_pages = state.totalPages;
3473
4792
  if (columns) payload.columns = columns;
3474
- const response = await client.updateGateway(payload, mergedOptions);
3475
- return formatGatewayResult(response, { table: resolvedTableName, operation: "update" });
4793
+ const sql = buildUpdateDebugSql(payload);
4794
+ return executeWithQueryTrace(
4795
+ tracer,
4796
+ {
4797
+ operation: "update",
4798
+ endpoint: "/gateway/update",
4799
+ table: resolvedTableName,
4800
+ sql,
4801
+ payload,
4802
+ options: mergedOptions
4803
+ },
4804
+ async () => {
4805
+ const response = await client.updateGateway(payload, mergedOptions);
4806
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "update" });
4807
+ },
4808
+ callsite
4809
+ );
3476
4810
  };
3477
- const mutation = createMutationQuery(executeUpdate, null);
4811
+ const mutation = createMutationQuery(executeUpdate, null, tracer, mutationCallsite);
3478
4812
  const updateChain = {};
3479
4813
  const filterMethods2 = createFilterMethods(state, addCondition, updateChain);
3480
4814
  Object.assign(updateChain, filterMethods2, mutation);
@@ -3486,7 +4820,8 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
3486
4820
  if (!resourceId && !filters?.length) {
3487
4821
  throw new Error('delete requires a resource_id either via eq("resource_id", ...) or options.resourceId');
3488
4822
  }
3489
- const executeDelete = async (columns, selectOptions) => {
4823
+ const mutationCallsite = captureTraceCallsite(tracer);
4824
+ const executeDelete = async (columns, selectOptions, callsite) => {
3490
4825
  const mergedOptions = mergeOptions(options, selectOptions);
3491
4826
  const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
3492
4827
  const payload = {
@@ -3499,13 +4834,33 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
3499
4834
  if (state.pageSize !== void 0) payload.page_size = state.pageSize;
3500
4835
  if (state.totalPages !== void 0) payload.total_pages = state.totalPages;
3501
4836
  if (columns) payload.columns = columns;
3502
- const response = await client.deleteGateway(payload, mergedOptions);
3503
- return formatGatewayResult(response, { table: resolvedTableName, operation: "delete" });
4837
+ const sql = buildDeleteDebugSql(payload);
4838
+ return executeWithQueryTrace(
4839
+ tracer,
4840
+ {
4841
+ operation: "delete",
4842
+ endpoint: "/gateway/delete",
4843
+ table: resolvedTableName,
4844
+ sql,
4845
+ payload,
4846
+ options: mergedOptions
4847
+ },
4848
+ async () => {
4849
+ const response = await client.deleteGateway(payload, mergedOptions);
4850
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "delete" });
4851
+ },
4852
+ callsite
4853
+ );
3504
4854
  };
3505
- return createMutationQuery(executeDelete, null);
4855
+ return createMutationQuery(executeDelete, null, tracer, mutationCallsite);
3506
4856
  },
3507
4857
  async single(columns, options) {
3508
- const response = await builder.select(columns, options);
4858
+ const response = await runSelect(
4859
+ columns ?? DEFAULT_COLUMNS,
4860
+ options,
4861
+ snapshotState(),
4862
+ captureTraceCallsite(tracer)
4863
+ );
3509
4864
  return toSingleResult(response);
3510
4865
  },
3511
4866
  async maybeSingle(columns, options) {
@@ -3514,14 +4869,29 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
3514
4869
  });
3515
4870
  return builder;
3516
4871
  }
3517
- function createQueryBuilder(client, formatGatewayResult) {
4872
+ function createQueryBuilder(client, formatGatewayResult, tracer) {
3518
4873
  return async function query(query, options) {
3519
4874
  const normalizedQuery = query.trim();
3520
4875
  if (!normalizedQuery) {
3521
4876
  throw new Error("query requires a non-empty string");
3522
4877
  }
3523
- const response = await client.queryGateway({ query: normalizedQuery }, options);
3524
- return formatGatewayResult(response, { operation: "query" });
4878
+ const payload = { query: normalizedQuery };
4879
+ const callsite = captureTraceCallsite(tracer);
4880
+ return executeWithQueryTrace(
4881
+ tracer,
4882
+ {
4883
+ operation: "query",
4884
+ endpoint: "/gateway/query",
4885
+ sql: normalizedQuery,
4886
+ payload,
4887
+ options
4888
+ },
4889
+ async () => {
4890
+ const response = await client.queryGateway(payload, options);
4891
+ return formatGatewayResult(response, { operation: "query" });
4892
+ },
4893
+ callsite
4894
+ );
3525
4895
  };
3526
4896
  }
3527
4897
  function createClientFromConfig(config) {
@@ -3532,9 +4902,10 @@ function createClientFromConfig(config) {
3532
4902
  backend: config.backend,
3533
4903
  headers: config.headers
3534
4904
  });
3535
- const formatGatewayResult = createResultFormatter(config.experimental);
4905
+ const formatGatewayResult = createResultFormatter();
4906
+ const queryTracer = createQueryTracer(config.experimental);
3536
4907
  const auth = createAuthClient(config.auth);
3537
- const from = (table) => createTableBuilder(table, gateway, formatGatewayResult);
4908
+ const from = (table) => createTableBuilder(table, gateway, formatGatewayResult, queryTracer, config.experimental);
3538
4909
  const rpc = (fn, args, options) => {
3539
4910
  const normalizedFn = fn.trim();
3540
4911
  if (!normalizedFn) {
@@ -3545,10 +4916,12 @@ function createClientFromConfig(config) {
3545
4916
  args,
3546
4917
  options,
3547
4918
  gateway,
3548
- formatGatewayResult
4919
+ formatGatewayResult,
4920
+ queryTracer,
4921
+ captureTraceCallsite(queryTracer)
3549
4922
  );
3550
4923
  };
3551
- const query = createQueryBuilder(gateway, formatGatewayResult);
4924
+ const query = createQueryBuilder(gateway, formatGatewayResult, queryTracer);
3552
4925
  const db = createDbModule({ from, rpc, query });
3553
4926
  return {
3554
4927
  from,
@@ -4018,7 +5391,7 @@ var AthenaGatewayCatalogClient = class {
4018
5391
  async queryRows(query) {
4019
5392
  const result = await this.client.query(query);
4020
5393
  if (result.error || result.status < 200 || result.status >= 300) {
4021
- throw new Error(result.error ?? `Gateway query failed with status ${result.status}`);
5394
+ throw new Error(result.error?.message ?? `Gateway query failed with status ${result.status}`);
4022
5395
  }
4023
5396
  return result.data ?? [];
4024
5397
  }
@@ -4115,10 +5488,24 @@ function resolveGeneratorProvider(providerConfig, experimentalFlags) {
4115
5488
  }
4116
5489
 
4117
5490
  // src/generator/pipeline.ts
5491
+ function canOverwriteArtifact(file) {
5492
+ return file.kind === "model" || file.kind === "schema";
5493
+ }
5494
+ async function fileExists(path) {
5495
+ try {
5496
+ await stat(path);
5497
+ return true;
5498
+ } catch {
5499
+ return false;
5500
+ }
5501
+ }
4118
5502
  async function writeArtifacts(files, cwd) {
4119
5503
  const writtenFiles = [];
4120
5504
  for (const file of files) {
4121
5505
  const absolutePath = resolve(cwd, file.path);
5506
+ if (!canOverwriteArtifact(file) && await fileExists(absolutePath)) {
5507
+ continue;
5508
+ }
4122
5509
  await mkdir(dirname(absolutePath), { recursive: true });
4123
5510
  await writeFile(absolutePath, file.content, "utf8");
4124
5511
  writtenFiles.push(file.path);