@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/browser.cjs CHANGED
@@ -88,23 +88,39 @@ function normalizeHeaderValue(value) {
88
88
  function isRecord(value) {
89
89
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
90
90
  }
91
+ function nonEmptyString(value) {
92
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
93
+ }
94
+ function resolveStructuredErrorPayload(payload) {
95
+ if (!isRecord(payload)) return null;
96
+ return isRecord(payload.error) ? payload.error : payload;
97
+ }
91
98
  function resolveRequestId(headers) {
92
99
  return headers.get("x-request-id") ?? headers.get("x-correlation-id") ?? headers.get("x-athena-request-id") ?? void 0;
93
100
  }
94
101
  function resolveErrorMessage(payload, fallback) {
95
- if (isRecord(payload)) {
96
- const messageCandidates = [payload.error, payload.message, payload.details];
102
+ const structuredPayload = resolveStructuredErrorPayload(payload);
103
+ if (structuredPayload) {
104
+ const messageCandidates = [structuredPayload.message, structuredPayload.error, structuredPayload.details];
97
105
  for (const candidate of messageCandidates) {
98
- if (typeof candidate === "string" && candidate.trim().length > 0) {
99
- return candidate.trim();
100
- }
106
+ const resolved = nonEmptyString(candidate);
107
+ if (resolved) return resolved;
101
108
  }
102
109
  }
103
- if (typeof payload === "string" && payload.trim().length > 0) {
104
- return payload.trim();
105
- }
110
+ const rawMessage = nonEmptyString(payload);
111
+ if (rawMessage) return rawMessage;
106
112
  return fallback;
107
113
  }
114
+ function resolveErrorHint(payload) {
115
+ const structuredPayload = resolveStructuredErrorPayload(payload);
116
+ return structuredPayload ? nonEmptyString(structuredPayload.hint) : void 0;
117
+ }
118
+ function resolveStatusText(response, payload) {
119
+ const rawStatusText = nonEmptyString(response.statusText);
120
+ if (rawStatusText) return rawStatusText;
121
+ const payloadRecord = isRecord(payload) ? payload : null;
122
+ return payloadRecord ? nonEmptyString(payloadRecord.statusText) ?? null : null;
123
+ }
108
124
  function detailsFromError(error) {
109
125
  return error.toDetails();
110
126
  }
@@ -275,6 +291,7 @@ async function callAthena(config, endpoint, method, payload, options) {
275
291
  return {
276
292
  ok: false,
277
293
  status: response.status,
294
+ statusText: resolveStatusText(response, parsedBody.parsed),
278
295
  data: null,
279
296
  error: invalidJsonError.message,
280
297
  errorDetails: detailsFromError(invalidJsonError),
@@ -293,11 +310,13 @@ async function callAthena(config, endpoint, method, payload, options) {
293
310
  status: response.status,
294
311
  endpoint,
295
312
  method,
296
- requestId
313
+ requestId,
314
+ hint: resolveErrorHint(parsed)
297
315
  });
298
316
  return {
299
317
  ok: false,
300
318
  status: response.status,
319
+ statusText: resolveStatusText(response, parsed),
301
320
  data: null,
302
321
  error: httpError.message,
303
322
  errorDetails: detailsFromError(httpError),
@@ -309,6 +328,7 @@ async function callAthena(config, endpoint, method, payload, options) {
309
328
  return {
310
329
  ok: true,
311
330
  status: response.status,
331
+ statusText: resolveStatusText(response, parsed),
312
332
  data: payloadData ?? null,
313
333
  count: payloadCount,
314
334
  error: void 0,
@@ -328,6 +348,7 @@ async function callAthena(config, endpoint, method, payload, options) {
328
348
  return {
329
349
  ok: false,
330
350
  status: 0,
351
+ statusText: null,
331
352
  data: null,
332
353
  error: networkError.message,
333
354
  errorDetails: detailsFromError(networkError),
@@ -369,10 +390,29 @@ function createAthenaGatewayClient(config = {}) {
369
390
  // src/sql-identifiers.ts
370
391
  var SIMPLE_IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
371
392
  var COMPOSITE_IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/;
372
- var ALIAS_PATTERN = /^([A-Za-z_][A-Za-z0-9_.]*)\s+(?:as\s+)?([A-Za-z_][A-Za-z0-9_]*)$/i;
393
+ var SQL_ALIAS_PATTERN = /^([A-Za-z_][A-Za-z0-9_.]*)\s+(?:as\s+)?([A-Za-z_][A-Za-z0-9_]*)$/i;
394
+ var RESPONSE_ALIAS_PATTERN = /^([A-Za-z_][A-Za-z0-9_]*)\s*:\s*([A-Za-z_][A-Za-z0-9_.]*)$/i;
373
395
  function quoteIdentifierSegment(identifier2) {
374
396
  return `"${identifier2.replace(/"/g, '""')}"`;
375
397
  }
398
+ function parseAliasedIdentifierToken(token) {
399
+ const responseAliasMatch = RESPONSE_ALIAS_PATTERN.exec(token);
400
+ if (responseAliasMatch) {
401
+ const [, aliasIdentifier2, baseIdentifier2] = responseAliasMatch;
402
+ if (COMPOSITE_IDENTIFIER_PATTERN.test(baseIdentifier2) && SIMPLE_IDENTIFIER_PATTERN.test(aliasIdentifier2)) {
403
+ return { baseIdentifier: baseIdentifier2, aliasIdentifier: aliasIdentifier2 };
404
+ }
405
+ }
406
+ const sqlAliasMatch = SQL_ALIAS_PATTERN.exec(token);
407
+ if (!sqlAliasMatch) {
408
+ return null;
409
+ }
410
+ const [, baseIdentifier, aliasIdentifier] = sqlAliasMatch;
411
+ if (!COMPOSITE_IDENTIFIER_PATTERN.test(baseIdentifier) || !SIMPLE_IDENTIFIER_PATTERN.test(aliasIdentifier)) {
412
+ return null;
413
+ }
414
+ return { baseIdentifier, aliasIdentifier };
415
+ }
376
416
  function quoteQualifiedIdentifier(identifier2) {
377
417
  return identifier2.split(".").map((segment) => quoteIdentifierSegment(segment)).join(".");
378
418
  }
@@ -381,23 +421,27 @@ function quoteSelectToken(token) {
381
421
  if (COMPOSITE_IDENTIFIER_PATTERN.test(token)) {
382
422
  return quoteQualifiedIdentifier(token);
383
423
  }
384
- const aliasMatch = ALIAS_PATTERN.exec(token);
385
- if (!aliasMatch) {
386
- return token;
387
- }
388
- const [, baseIdentifier, aliasIdentifier] = aliasMatch;
389
- if (!COMPOSITE_IDENTIFIER_PATTERN.test(baseIdentifier) || !SIMPLE_IDENTIFIER_PATTERN.test(aliasIdentifier)) {
424
+ const aliasedIdentifier = parseAliasedIdentifierToken(token);
425
+ if (!aliasedIdentifier) {
390
426
  return token;
391
427
  }
428
+ const { baseIdentifier, aliasIdentifier } = aliasedIdentifier;
392
429
  return `${quoteQualifiedIdentifier(baseIdentifier)} AS ${quoteIdentifierSegment(aliasIdentifier)}`;
393
430
  }
431
+ function quoteSelectColumnToken(token) {
432
+ const trimmed = token.trim();
433
+ if (!trimmed || trimmed === "*") return trimmed || "*";
434
+ const responseAliasMatch = RESPONSE_ALIAS_PATTERN.exec(trimmed);
435
+ if (responseAliasMatch) {
436
+ const [, aliasIdentifier, baseIdentifier] = responseAliasMatch;
437
+ return `${quoteQualifiedIdentifier(baseIdentifier)} AS ${quoteIdentifierSegment(aliasIdentifier)}`;
438
+ }
439
+ return quoteQualifiedIdentifier(trimmed);
440
+ }
394
441
  function canAutoQuoteToken(token) {
395
442
  if (token === "*") return true;
396
443
  if (COMPOSITE_IDENTIFIER_PATTERN.test(token)) return true;
397
- const aliasMatch = ALIAS_PATTERN.exec(token);
398
- if (!aliasMatch) return false;
399
- const [, baseIdentifier, aliasIdentifier] = aliasMatch;
400
- return COMPOSITE_IDENTIFIER_PATTERN.test(baseIdentifier) && SIMPLE_IDENTIFIER_PATTERN.test(aliasIdentifier);
444
+ return parseAliasedIdentifierToken(token) != null;
401
445
  }
402
446
  function splitTopLevelCommaSeparated(input) {
403
447
  const parts = [];
@@ -497,6 +541,231 @@ function identifier(...segments) {
497
541
  return new SqlIdentifierPath(expandedSegments);
498
542
  }
499
543
 
544
+ // src/auth/react-email.ts
545
+ var reactEmailRenderModulePromise;
546
+ function isRecord2(value) {
547
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
548
+ }
549
+ function isFunction(value) {
550
+ return typeof value === "function";
551
+ }
552
+ function toStringOrUndefined(value) {
553
+ if (typeof value !== "string") return void 0;
554
+ return value;
555
+ }
556
+ function nowIsoString() {
557
+ return (/* @__PURE__ */ new Date()).toISOString();
558
+ }
559
+ function emitReactEmailEvent(observe, phase, input = {}) {
560
+ if (!observe) return;
561
+ try {
562
+ observe({
563
+ phase,
564
+ timestamp: nowIsoString(),
565
+ ...input
566
+ });
567
+ } catch {
568
+ }
569
+ }
570
+ function mergeRenderDefaults(input, defaults) {
571
+ return {
572
+ ...input,
573
+ pretty: input.pretty ?? defaults?.pretty,
574
+ includePlainText: input.includePlainText ?? defaults?.includePlainText
575
+ };
576
+ }
577
+ function mergeRuntimeOptions(options) {
578
+ if (!options) return void 0;
579
+ return {
580
+ defaults: options.defaults,
581
+ observe: options.observe,
582
+ route: "route" in options ? options.route : void 0
583
+ };
584
+ }
585
+ async function resolveReactEmailRenderModule() {
586
+ if (!reactEmailRenderModulePromise) {
587
+ reactEmailRenderModulePromise = (async () => {
588
+ try {
589
+ const loaded = await import('@react-email/render');
590
+ if (!isFunction(loaded.render)) {
591
+ throw new Error("missing render(...) export");
592
+ }
593
+ return {
594
+ render: loaded.render,
595
+ toPlainText: isFunction(loaded.toPlainText) ? loaded.toPlainText : void 0,
596
+ pretty: isFunction(loaded.pretty) ? loaded.pretty : void 0
597
+ };
598
+ } catch (error) {
599
+ const message = error instanceof Error ? error.message : String(error);
600
+ throw new Error(
601
+ `React Email rendering requires @react-email/render. Install it in your project (for example: pnpm add @react-email/render). Loader error: ${message}`
602
+ );
603
+ }
604
+ })();
605
+ }
606
+ if (!reactEmailRenderModulePromise) {
607
+ throw new Error("React Email renderer module failed to initialize");
608
+ }
609
+ return reactEmailRenderModulePromise;
610
+ }
611
+ async function resolveReactEmailElement(input) {
612
+ if (input.element != null) {
613
+ return input.element;
614
+ }
615
+ if (!input.component) {
616
+ throw new Error("react email payload requires either `element` or `component`");
617
+ }
618
+ try {
619
+ const reactModule = await import('react');
620
+ if (typeof reactModule.createElement !== "function") {
621
+ throw new Error("react createElement(...) export is unavailable");
622
+ }
623
+ return reactModule.createElement(
624
+ input.component,
625
+ input.props ?? {}
626
+ );
627
+ } catch (error) {
628
+ const message = error instanceof Error ? error.message : String(error);
629
+ throw new Error(
630
+ `React Email component rendering requires react runtime support. Install react in your project. Loader error: ${message}`
631
+ );
632
+ }
633
+ }
634
+ function createAuthReactEmailInput(component, props, overrides = {}) {
635
+ return {
636
+ ...overrides,
637
+ component,
638
+ props
639
+ };
640
+ }
641
+ function defineAuthEmailTemplate(definition) {
642
+ const react = (props, overrides) => createAuthReactEmailInput(definition.component, props, {
643
+ ...definition.defaults,
644
+ ...overrides
645
+ });
646
+ return {
647
+ component: definition.component,
648
+ react,
649
+ toTemplateCreate: (input) => {
650
+ const templateKey = input.templateKey ?? definition.templateKey;
651
+ const subjectTemplate = input.subjectTemplate ?? definition.subjectTemplate;
652
+ if (!templateKey) {
653
+ throw new Error("defineAuthEmailTemplate.toTemplateCreate requires templateKey");
654
+ }
655
+ if (!subjectTemplate) {
656
+ throw new Error("defineAuthEmailTemplate.toTemplateCreate requires subjectTemplate");
657
+ }
658
+ const { props, react: reactOverrides, ...rest } = input;
659
+ return {
660
+ ...rest,
661
+ templateKey,
662
+ subjectTemplate,
663
+ react: react(props, reactOverrides)
664
+ };
665
+ },
666
+ toTemplateUpdate: (input) => {
667
+ const { props, react: reactOverrides, ...rest } = input;
668
+ return {
669
+ ...rest,
670
+ react: react(props, reactOverrides)
671
+ };
672
+ }
673
+ };
674
+ }
675
+ async function renderAthenaReactEmail(input, options) {
676
+ if (!isRecord2(input)) {
677
+ throw new Error("react email payload must be an object");
678
+ }
679
+ const runtimeOptions = mergeRuntimeOptions(options);
680
+ const start = Date.now();
681
+ emitReactEmailEvent(runtimeOptions?.observe, "render:start", {
682
+ route: runtimeOptions?.route,
683
+ message: "Rendering react email payload"
684
+ });
685
+ try {
686
+ const normalizedInput = mergeRenderDefaults(input, runtimeOptions?.defaults);
687
+ const element = await resolveReactEmailElement(normalizedInput);
688
+ const renderModule = await resolveReactEmailRenderModule();
689
+ const htmlValue = await renderModule.render(element);
690
+ const renderedHtml = typeof htmlValue === "string" ? htmlValue : String(htmlValue ?? "");
691
+ if (!renderedHtml.trim()) {
692
+ throw new Error("react email renderer returned an empty HTML string");
693
+ }
694
+ let html = renderedHtml;
695
+ if (normalizedInput.pretty && renderModule.pretty) {
696
+ const prettyValue = await renderModule.pretty(renderedHtml);
697
+ if (typeof prettyValue === "string" && prettyValue.trim().length > 0) {
698
+ html = prettyValue;
699
+ }
700
+ }
701
+ const explicitText = toStringOrUndefined(normalizedInput.text);
702
+ if (explicitText !== void 0) {
703
+ emitReactEmailEvent(runtimeOptions?.observe, "render:success", {
704
+ route: runtimeOptions?.route,
705
+ durationMs: Date.now() - start,
706
+ message: "Rendered react email with explicit text"
707
+ });
708
+ return {
709
+ html,
710
+ text: explicitText
711
+ };
712
+ }
713
+ if (normalizedInput.includePlainText === false || !renderModule.toPlainText) {
714
+ emitReactEmailEvent(runtimeOptions?.observe, "render:success", {
715
+ route: runtimeOptions?.route,
716
+ durationMs: Date.now() - start,
717
+ message: "Rendered react email without plain-text derivation"
718
+ });
719
+ return { html };
720
+ }
721
+ const plainTextValue = await renderModule.toPlainText(html);
722
+ const plainText = toStringOrUndefined(plainTextValue);
723
+ emitReactEmailEvent(runtimeOptions?.observe, "render:success", {
724
+ route: runtimeOptions?.route,
725
+ durationMs: Date.now() - start,
726
+ message: plainText ? "Rendered react email with derived plain text" : "Rendered react email HTML only"
727
+ });
728
+ if (plainText === void 0) {
729
+ return { html };
730
+ }
731
+ return {
732
+ html,
733
+ text: plainText
734
+ };
735
+ } catch (error) {
736
+ const message = error instanceof Error ? error.message : String(error);
737
+ emitReactEmailEvent(runtimeOptions?.observe, "render:error", {
738
+ route: runtimeOptions?.route,
739
+ durationMs: Date.now() - start,
740
+ error: message,
741
+ message: "Failed to render react email payload"
742
+ });
743
+ throw error;
744
+ }
745
+ }
746
+ async function resolveReactEmailPayloadFields(input, fields, options) {
747
+ const { react, ...payloadWithoutReact } = input;
748
+ if (!react) {
749
+ return payloadWithoutReact;
750
+ }
751
+ const rendered = await renderAthenaReactEmail(react, options);
752
+ const payload = {
753
+ ...payloadWithoutReact
754
+ };
755
+ payload[fields.htmlField] = rendered.html;
756
+ const currentTextValue = payload[fields.textField];
757
+ if (rendered.text !== void 0 && (currentTextValue === void 0 || currentTextValue === null || currentTextValue === "")) {
758
+ payload[fields.textField] = rendered.text;
759
+ }
760
+ if (fields.variablesField && (payload[fields.variablesField] === void 0 || payload[fields.variablesField] === null) && isRecord2(react.props)) {
761
+ const derivedVariables = Object.keys(react.props);
762
+ if (derivedVariables.length > 0) {
763
+ payload[fields.variablesField] = derivedVariables;
764
+ }
765
+ }
766
+ return payload;
767
+ }
768
+
500
769
  // src/auth/client.ts
501
770
  var DEFAULT_AUTH_BASE_URL = "http://localhost:3001/api/auth";
502
771
  var FALLBACK_SDK_VERSION2 = "1.0.0";
@@ -506,7 +775,7 @@ var SDK_HEADER_VALUE2 = `${SDK_NAME2} ${SDK_VERSION2}`;
506
775
  function normalizeBaseUrl(baseUrl) {
507
776
  return (baseUrl ?? DEFAULT_AUTH_BASE_URL).replace(/\/$/, "");
508
777
  }
509
- function isRecord2(value) {
778
+ function isRecord3(value) {
510
779
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
511
780
  }
512
781
  function normalizeHeaderValue2(value) {
@@ -531,7 +800,7 @@ function resolveRequestId2(headers) {
531
800
  return headers.get("x-request-id") ?? headers.get("x-correlation-id") ?? headers.get("x-athena-request-id") ?? void 0;
532
801
  }
533
802
  function resolveErrorMessage2(payload, fallback) {
534
- if (isRecord2(payload)) {
803
+ if (isRecord3(payload)) {
535
804
  const messageCandidates = [payload.error, payload.message, payload.details];
536
805
  for (const candidate of messageCandidates) {
537
806
  if (typeof candidate === "string" && candidate.trim().length > 0) {
@@ -857,6 +1126,19 @@ function createAuthClient(config = {}) {
857
1126
  options
858
1127
  );
859
1128
  };
1129
+ const withReactEmailRoute = (route) => ({
1130
+ ...resolvedConfig.reactEmail,
1131
+ route
1132
+ });
1133
+ const resolveAdminEmailPayload = (route, input) => resolveReactEmailPayloadFields(input, {
1134
+ htmlField: "htmlBody",
1135
+ textField: "textBody"
1136
+ }, withReactEmailRoute(route));
1137
+ const resolveAdminEmailTemplatePayload = (route, input) => resolveReactEmailPayloadFields(input, {
1138
+ htmlField: "htmlTemplate",
1139
+ textField: "textTemplate",
1140
+ variablesField: "variables"
1141
+ }, withReactEmailRoute(route));
860
1142
  const listUserEmailsWithFallback = async (input, options) => {
861
1143
  const primary = await getWithQuery(
862
1144
  "/email/list",
@@ -884,7 +1166,7 @@ function createAuthClient(config = {}) {
884
1166
  data: null
885
1167
  };
886
1168
  }
887
- const fallbackStatus = isRecord2(fallback.data) && typeof fallback.data.ok === "boolean" ? fallback.data.ok ? "ok" : "error" : "ok";
1169
+ const fallbackStatus = isRecord3(fallback.data) && typeof fallback.data.ok === "boolean" ? fallback.data.ok ? "ok" : "error" : "ok";
888
1170
  return {
889
1171
  ...fallback,
890
1172
  data: {
@@ -1320,8 +1602,16 @@ function createAuthClient(config = {}) {
1320
1602
  email: {
1321
1603
  list: (input, options) => getWithQuery("/admin/email/list", input, options),
1322
1604
  get: (input, options) => getWithQuery("/admin/email/get", input, options),
1323
- create: (input, options) => postGeneric("/admin/email/create", input, options),
1324
- update: (input, options) => postGeneric("/admin/email/update", input, options),
1605
+ create: async (input, options) => postGeneric(
1606
+ "/admin/email/create",
1607
+ await resolveAdminEmailPayload("/admin/email/create", input),
1608
+ options
1609
+ ),
1610
+ update: async (input, options) => postGeneric(
1611
+ "/admin/email/update",
1612
+ await resolveAdminEmailPayload("/admin/email/update", input),
1613
+ options
1614
+ ),
1325
1615
  delete: (input, options) => postGeneric("/admin/email/delete", input, options),
1326
1616
  failure: {
1327
1617
  list: (input, options) => getWithQuery("/admin/email-failure/list", input, options),
@@ -1333,17 +1623,33 @@ function createAuthClient(config = {}) {
1333
1623
  template: {
1334
1624
  list: (input, options) => getWithQuery("/admin/email-template/list", input, options),
1335
1625
  get: (input, options) => getWithQuery("/admin/email-template/get", input, options),
1336
- create: (input, options) => postGeneric("/admin/email-template/create", input, options),
1337
- update: (input, options) => postGeneric("/admin/email-template/update", input, options),
1626
+ create: async (input, options) => postGeneric(
1627
+ "/admin/email-template/create",
1628
+ await resolveAdminEmailTemplatePayload("/admin/email-template/create", input),
1629
+ options
1630
+ ),
1631
+ update: async (input, options) => postGeneric(
1632
+ "/admin/email-template/update",
1633
+ await resolveAdminEmailTemplatePayload("/admin/email-template/update", input),
1634
+ options
1635
+ ),
1338
1636
  delete: (input, options) => postGeneric("/admin/email-template/delete", input, options)
1339
1637
  }
1340
1638
  },
1341
1639
  emailTemplate: {
1342
1640
  get: (input, options) => getWithQuery("/admin/email-template/get", input, options),
1343
- create: (input, options) => postGeneric("/admin/email-template/create", input, options),
1641
+ create: async (input, options) => postGeneric(
1642
+ "/admin/email-template/create",
1643
+ await resolveAdminEmailTemplatePayload("/admin/email-template/create", input),
1644
+ options
1645
+ ),
1344
1646
  delete: (input, options) => postGeneric("/admin/email-template/delete", input, options),
1345
1647
  list: (input, options) => getWithQuery("/admin/email-template/list", input, options),
1346
- update: (input, options) => postGeneric("/admin/email-template/update", input, options)
1648
+ update: async (input, options) => postGeneric(
1649
+ "/admin/email-template/update",
1650
+ await resolveAdminEmailTemplatePayload("/admin/email-template/update", input),
1651
+ options
1652
+ )
1347
1653
  }
1348
1654
  },
1349
1655
  apiKey: {
@@ -1535,6 +1841,19 @@ function createAuthClient(config = {}) {
1535
1841
  };
1536
1842
  }
1537
1843
 
1844
+ // src/utils/parse-boolean-flag.ts
1845
+ function parseBooleanFlag(rawValue, fallback) {
1846
+ if (!rawValue) return fallback;
1847
+ const normalized = rawValue.trim().toLowerCase();
1848
+ if (normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on") {
1849
+ return true;
1850
+ }
1851
+ if (normalized === "0" || normalized === "false" || normalized === "no" || normalized === "off") {
1852
+ return false;
1853
+ }
1854
+ return fallback;
1855
+ }
1856
+
1538
1857
  // src/auxiliaries.ts
1539
1858
  var AthenaErrorKind = {
1540
1859
  UniqueViolation: "unique_violation",
@@ -1564,16 +1883,8 @@ var AthenaErrorCategory = {
1564
1883
  Database: "database",
1565
1884
  Unknown: "unknown"
1566
1885
  };
1567
- function parseBooleanFlag(rawValue, fallback) {
1568
- if (!rawValue) return fallback;
1569
- const normalized = rawValue.trim().toLowerCase();
1570
- if (normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on") {
1571
- return true;
1572
- }
1573
- if (normalized === "0" || normalized === "false" || normalized === "no" || normalized === "off") {
1574
- return false;
1575
- }
1576
- return fallback;
1886
+ function parseBooleanFlag2(rawValue, fallback) {
1887
+ return parseBooleanFlag(rawValue, fallback);
1577
1888
  }
1578
1889
  var AthenaError = class extends Error {
1579
1890
  code;
@@ -1597,9 +1908,38 @@ var AthenaError = class extends Error {
1597
1908
  this.raw = input.raw;
1598
1909
  }
1599
1910
  };
1600
- function isRecord3(value) {
1911
+ function isRecord4(value) {
1601
1912
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1602
1913
  }
1914
+ function firstNonEmptyString(...values) {
1915
+ for (const value of values) {
1916
+ if (typeof value === "string" && value.trim().length > 0) {
1917
+ return value.trim();
1918
+ }
1919
+ }
1920
+ return void 0;
1921
+ }
1922
+ function messageFromUnknownError(error) {
1923
+ if (typeof error === "string" && error.trim().length > 0) {
1924
+ return error.trim();
1925
+ }
1926
+ if (error instanceof Error && error.message.trim().length > 0) {
1927
+ return error.message.trim();
1928
+ }
1929
+ if (!isRecord4(error)) {
1930
+ return void 0;
1931
+ }
1932
+ return firstNonEmptyString(error.message, error.error, error.details);
1933
+ }
1934
+ function gatewayCodeFromUnknownError(error) {
1935
+ if (!isRecord4(error) || typeof error.gatewayCode !== "string") {
1936
+ return void 0;
1937
+ }
1938
+ return error.gatewayCode;
1939
+ }
1940
+ function isAthenaResultErrorLike(value) {
1941
+ return isRecord4(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");
1942
+ }
1603
1943
  function isAthenaErrorKind(value) {
1604
1944
  return value === "unique_violation" || value === "not_found" || value === "validation" || value === "auth" || value === "rate_limit" || value === "transient" || value === "unknown";
1605
1945
  }
@@ -1610,7 +1950,7 @@ function isAthenaErrorCategory(value) {
1610
1950
  return value === "transport" || value === "client" || value === "server" || value === "database" || value === "unknown";
1611
1951
  }
1612
1952
  function isNormalizedAthenaError(value) {
1613
- return isRecord3(value) && isAthenaErrorKind(value.kind) && isAthenaErrorCode(value.code) && isAthenaErrorCategory(value.category) && typeof value.retryable === "boolean" && typeof value.message === "string" && "raw" in value;
1953
+ return isRecord4(value) && isAthenaErrorKind(value.kind) && isAthenaErrorCode(value.code) && isAthenaErrorCategory(value.category) && typeof value.retryable === "boolean" && typeof value.message === "string" && "raw" in value;
1614
1954
  }
1615
1955
  function withContextOverrides(normalized, context) {
1616
1956
  if (!context?.table && !context?.operation) {
@@ -1623,7 +1963,7 @@ function withContextOverrides(normalized, context) {
1623
1963
  };
1624
1964
  }
1625
1965
  function resolveAttachedNormalizedError(resultOrError) {
1626
- if (!isRecord3(resultOrError)) return void 0;
1966
+ if (!isRecord4(resultOrError)) return void 0;
1627
1967
  if (!("__athenaNormalizedError" in resultOrError)) return void 0;
1628
1968
  const candidate = resultOrError.__athenaNormalizedError;
1629
1969
  return isNormalizedAthenaError(candidate) ? candidate : void 0;
@@ -1642,7 +1982,7 @@ function contextHint(context) {
1642
1982
  return `Identity: ${identity}`;
1643
1983
  }
1644
1984
  function isAthenaResultLike(value) {
1645
- return isRecord3(value) && "status" in value && "error" in value && "data" in value && typeof value.status === "number";
1985
+ return isRecord4(value) && "status" in value && "error" in value && "data" in value && typeof value.status === "number";
1646
1986
  }
1647
1987
  function operationFromDetails(details) {
1648
1988
  if (!details?.endpoint) return void 0;
@@ -1739,15 +2079,16 @@ function toAthenaGatewayError(source, fallbackMessage, context) {
1739
2079
  return source;
1740
2080
  }
1741
2081
  if (isAthenaResultLike(source) && source.errorDetails) {
2082
+ const message2 = messageFromUnknownError(source.error) ?? source.errorDetails.message ?? fallbackMessage;
1742
2083
  return new AthenaGatewayError({
1743
2084
  code: source.errorDetails.code,
1744
- message: source.error ?? source.errorDetails.message,
2085
+ message: message2,
1745
2086
  status: source.status,
1746
2087
  endpoint: source.errorDetails.endpoint,
1747
2088
  method: source.errorDetails.method,
1748
2089
  requestId: source.errorDetails.requestId,
1749
- hint: source.errorDetails.hint,
1750
- cause: source.errorDetails.cause
2090
+ hint: (isRecord4(source.error) ? firstNonEmptyString(source.error.hint) : void 0) ?? source.errorDetails.hint,
2091
+ cause: (isRecord4(source.error) ? firstNonEmptyString(source.error.cause) : void 0) ?? source.errorDetails.cause
1751
2092
  });
1752
2093
  }
1753
2094
  const normalized = normalizeAthenaError(source, context);
@@ -1769,13 +2110,50 @@ function normalizeAthenaError(resultOrError, context) {
1769
2110
  return withContextOverrides(attached, context);
1770
2111
  }
1771
2112
  if (isAthenaResultLike(resultOrError)) {
2113
+ if (isAthenaResultErrorLike(resultOrError.error)) {
2114
+ return {
2115
+ kind: resultOrError.error.kind ?? classifyKind(resultOrError.status, gatewayCodeFromUnknownError(resultOrError.error), resultOrError.error.message),
2116
+ code: resultOrError.error.athenaCode ?? toAthenaErrorCode(
2117
+ resultOrError.error.kind ?? classifyKind(
2118
+ resultOrError.status,
2119
+ gatewayCodeFromUnknownError(resultOrError.error),
2120
+ resultOrError.error.message
2121
+ ),
2122
+ resultOrError.error.status ?? resultOrError.status,
2123
+ gatewayCodeFromUnknownError(resultOrError.error)
2124
+ ),
2125
+ category: resultOrError.error.category ?? toAthenaErrorCategory(
2126
+ resultOrError.error.kind ?? classifyKind(
2127
+ resultOrError.status,
2128
+ gatewayCodeFromUnknownError(resultOrError.error),
2129
+ resultOrError.error.message
2130
+ ),
2131
+ resultOrError.error.status ?? resultOrError.status
2132
+ ),
2133
+ retryable: resultOrError.error.retryable ?? isRetryable(
2134
+ resultOrError.error.kind ?? classifyKind(
2135
+ resultOrError.status,
2136
+ gatewayCodeFromUnknownError(resultOrError.error),
2137
+ resultOrError.error.message
2138
+ ),
2139
+ resultOrError.error.status ?? resultOrError.status
2140
+ ),
2141
+ status: resultOrError.error.status ?? resultOrError.status,
2142
+ constraint: resultOrError.error.constraint,
2143
+ table: context?.table ?? resultOrError.error.table,
2144
+ operation: context?.operation ?? resultOrError.error.operation,
2145
+ message: resultOrError.error.message,
2146
+ raw: resultOrError.error.raw ?? resultOrError.raw
2147
+ };
2148
+ }
1772
2149
  const details = resultOrError.errorDetails;
1773
- const message2 = resultOrError.error ?? details?.message ?? `Athena ${context?.operation ?? operationFromDetails(details) ?? "request"} failed`;
2150
+ const message2 = messageFromUnknownError(resultOrError.error) ?? details?.message ?? `Athena ${context?.operation ?? operationFromDetails(details) ?? "request"} failed`;
1774
2151
  const operation = context?.operation ?? operationFromDetails(details);
1775
2152
  const table = context?.table ?? extractTable(message2);
1776
2153
  const constraint = extractConstraint(message2);
1777
- const kind2 = classifyKind(resultOrError.status, details?.code, message2);
1778
- const code = toAthenaErrorCode(kind2, resultOrError.status, details?.code);
2154
+ const gatewayCode = details?.code ?? gatewayCodeFromUnknownError(resultOrError.error);
2155
+ const kind2 = classifyKind(resultOrError.status, gatewayCode, message2);
2156
+ const code = toAthenaErrorCode(kind2, resultOrError.status, gatewayCode);
1779
2157
  const category = toAthenaErrorCategory(kind2, resultOrError.status);
1780
2158
  return {
1781
2159
  kind: kind2,
@@ -1812,7 +2190,7 @@ function normalizeAthenaError(resultOrError, context) {
1812
2190
  };
1813
2191
  }
1814
2192
  if (resultOrError instanceof Error) {
1815
- const maybeStatus = isRecord3(resultOrError) && typeof resultOrError.status === "number" ? resultOrError.status : void 0;
2193
+ const maybeStatus = isRecord4(resultOrError) && typeof resultOrError.status === "number" ? resultOrError.status : void 0;
1816
2194
  const kind2 = classifyKind(maybeStatus, void 0, resultOrError.message);
1817
2195
  return {
1818
2196
  kind: kind2,
@@ -2029,17 +2407,282 @@ function createDbModule(input) {
2029
2407
  return db;
2030
2408
  }
2031
2409
 
2410
+ // src/query-ast.ts
2411
+ 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;
2412
+ var FILTER_OPERATORS = /* @__PURE__ */ new Set([
2413
+ "eq",
2414
+ "neq",
2415
+ "gt",
2416
+ "gte",
2417
+ "lt",
2418
+ "lte",
2419
+ "like",
2420
+ "ilike",
2421
+ "is",
2422
+ "in",
2423
+ "contains",
2424
+ "containedBy"
2425
+ ]);
2426
+ var BOOLEAN_SAFE_OPERATORS = /* @__PURE__ */ new Set([
2427
+ "eq",
2428
+ "neq",
2429
+ "gt",
2430
+ "gte",
2431
+ "lt",
2432
+ "lte",
2433
+ "like",
2434
+ "ilike",
2435
+ "is"
2436
+ ]);
2437
+ function isRecord5(value) {
2438
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
2439
+ }
2440
+ function isUuidString(value) {
2441
+ return UUID_PATTERN.test(value.trim());
2442
+ }
2443
+ function isUuidIdentifierColumn(column) {
2444
+ return column === "id" || /(?:^|_)uuid(?:_|$)/i.test(column) || /_id$/i.test(column);
2445
+ }
2446
+ function shouldUseUuidTextComparison(column, value) {
2447
+ return typeof value === "string" && isUuidString(value) && isUuidIdentifierColumn(column);
2448
+ }
2449
+ function isRelationSelectNode(value) {
2450
+ return isRecord5(value) && isRecord5(value.select);
2451
+ }
2452
+ function normalizeIdentifier(value, label) {
2453
+ const normalized = value.trim();
2454
+ if (!normalized) {
2455
+ throw new Error(`${label} must be a non-empty string`);
2456
+ }
2457
+ return normalized;
2458
+ }
2459
+ function stringifyFilterValue(value) {
2460
+ if (Array.isArray(value)) {
2461
+ return value.join(",");
2462
+ }
2463
+ return String(value);
2464
+ }
2465
+ function buildGatewayCondition(operator, column, value) {
2466
+ const condition = { operator };
2467
+ if (column) {
2468
+ condition.column = column;
2469
+ if (operator === "eq") {
2470
+ condition.eq_column = column;
2471
+ }
2472
+ }
2473
+ if (value !== void 0) {
2474
+ condition.value = value;
2475
+ if (operator === "eq") {
2476
+ condition.eq_value = value;
2477
+ }
2478
+ }
2479
+ if (operator === "eq" && column && value !== void 0 && shouldUseUuidTextComparison(column, value)) {
2480
+ condition.column_cast = "text";
2481
+ condition.eq_column_cast = "text";
2482
+ }
2483
+ return condition;
2484
+ }
2485
+ function compileRelationToken(key, node) {
2486
+ const nested = compileSelectShape(node.select);
2487
+ const propertyKey = normalizeIdentifier(key, "select relation key");
2488
+ const relationToken = normalizeIdentifier(node.via ?? propertyKey, "select relation token");
2489
+ const alias = node.as?.trim() || (relationToken !== propertyKey ? propertyKey : "");
2490
+ const prefix = alias ? `${alias}:` : "";
2491
+ return `${prefix}${relationToken}(${nested})`;
2492
+ }
2493
+ function compileSelectShape(select) {
2494
+ if (!isRecord5(select)) {
2495
+ throw new Error("findMany select must be an object");
2496
+ }
2497
+ const tokens = [];
2498
+ for (const [rawKey, rawValue] of Object.entries(select)) {
2499
+ if (rawValue === void 0) {
2500
+ continue;
2501
+ }
2502
+ if (rawValue === true) {
2503
+ tokens.push(normalizeIdentifier(rawKey, "select column"));
2504
+ continue;
2505
+ }
2506
+ if (isRelationSelectNode(rawValue)) {
2507
+ tokens.push(compileRelationToken(rawKey, rawValue));
2508
+ continue;
2509
+ }
2510
+ throw new Error(`Unsupported select node for "${rawKey}"`);
2511
+ }
2512
+ if (tokens.length === 0) {
2513
+ throw new Error("findMany select requires at least one field");
2514
+ }
2515
+ return tokens.join(",");
2516
+ }
2517
+ function compileColumnWhere(column, input) {
2518
+ const normalizedColumn = normalizeIdentifier(column, "where column");
2519
+ if (!isRecord5(input)) {
2520
+ return [buildGatewayCondition("eq", normalizedColumn, input)];
2521
+ }
2522
+ const conditions = [];
2523
+ for (const [rawOperator, rawValue] of Object.entries(input)) {
2524
+ if (rawValue === void 0) {
2525
+ continue;
2526
+ }
2527
+ if (!FILTER_OPERATORS.has(rawOperator)) {
2528
+ throw new Error(`Unsupported where operator "${rawOperator}" on "${normalizedColumn}"`);
2529
+ }
2530
+ if ((rawOperator === "in" || rawOperator === "contains" || rawOperator === "containedBy") && !Array.isArray(rawValue)) {
2531
+ throw new Error(`where.${normalizedColumn}.${rawOperator} requires an array value`);
2532
+ }
2533
+ conditions.push(
2534
+ buildGatewayCondition(
2535
+ rawOperator,
2536
+ normalizedColumn,
2537
+ rawValue
2538
+ )
2539
+ );
2540
+ }
2541
+ if (conditions.length === 0) {
2542
+ throw new Error(`where.${normalizedColumn} requires at least one operator`);
2543
+ }
2544
+ return conditions;
2545
+ }
2546
+ function compileBooleanExpressionTerms(clause, label) {
2547
+ if (!isRecord5(clause)) {
2548
+ throw new Error(`findMany where.${label} clauses must be objects`);
2549
+ }
2550
+ const entries = Object.entries(clause).filter(([, value]) => value !== void 0);
2551
+ if (entries.length !== 1) {
2552
+ throw new Error(`findMany where.${label} clauses must target exactly one column`);
2553
+ }
2554
+ const [rawColumn, rawValue] = entries[0];
2555
+ const column = normalizeIdentifier(rawColumn, `where.${label} column`);
2556
+ if (!isRecord5(rawValue)) {
2557
+ return [`${column}.eq.${stringifyFilterValue(rawValue)}`];
2558
+ }
2559
+ const operatorEntries = Object.entries(rawValue).filter(([, value]) => value !== void 0);
2560
+ if (operatorEntries.length === 0) {
2561
+ throw new Error(`findMany where.${label}.${column} requires at least one operator`);
2562
+ }
2563
+ if (label === "not" && operatorEntries.length > 1) {
2564
+ throw new Error("findMany where.not only supports a single lossless operator expression");
2565
+ }
2566
+ return operatorEntries.map(([rawOperator, rawOperand]) => {
2567
+ if (!BOOLEAN_SAFE_OPERATORS.has(rawOperator)) {
2568
+ throw new Error(`findMany where.${label} only supports lossless scalar operators`);
2569
+ }
2570
+ if (Array.isArray(rawOperand)) {
2571
+ throw new Error(`findMany where.${label} does not support array-valued operators`);
2572
+ }
2573
+ return `${column}.${rawOperator}.${stringifyFilterValue(rawOperand)}`;
2574
+ });
2575
+ }
2576
+ function compileWhere(where) {
2577
+ if (where === void 0) {
2578
+ return void 0;
2579
+ }
2580
+ if (!isRecord5(where)) {
2581
+ throw new Error("findMany where must be an object");
2582
+ }
2583
+ const conditions = [];
2584
+ for (const [rawKey, rawValue] of Object.entries(where)) {
2585
+ if (rawValue === void 0) {
2586
+ continue;
2587
+ }
2588
+ if (rawKey === "or") {
2589
+ if (!Array.isArray(rawValue) || rawValue.length === 0) {
2590
+ throw new Error("findMany where.or must be a non-empty array");
2591
+ }
2592
+ const expressions = rawValue.flatMap(
2593
+ (value) => compileBooleanExpressionTerms(value, "or")
2594
+ );
2595
+ conditions.push(buildGatewayCondition("or", void 0, expressions.join(",")));
2596
+ continue;
2597
+ }
2598
+ if (rawKey === "not") {
2599
+ const expressions = compileBooleanExpressionTerms(rawValue, "not");
2600
+ if (expressions.length !== 1) {
2601
+ throw new Error("findMany where.not must compile to exactly one lossless expression");
2602
+ }
2603
+ conditions.push(buildGatewayCondition("not", void 0, expressions[0]));
2604
+ continue;
2605
+ }
2606
+ conditions.push(...compileColumnWhere(rawKey, rawValue));
2607
+ }
2608
+ return conditions.length > 0 ? conditions : void 0;
2609
+ }
2610
+ function resolveOrderDirection(input) {
2611
+ if (typeof input === "boolean") {
2612
+ return input === false ? "descending" : "ascending";
2613
+ }
2614
+ if (typeof input === "string") {
2615
+ const normalized = input.trim().toLowerCase();
2616
+ if (normalized === "asc" || normalized === "ascending") {
2617
+ return "ascending";
2618
+ }
2619
+ if (normalized === "desc" || normalized === "descending") {
2620
+ return "descending";
2621
+ }
2622
+ throw new Error(`Unsupported orderBy direction "${input}"`);
2623
+ }
2624
+ return input.ascending === false ? "descending" : "ascending";
2625
+ }
2626
+ function compileOrderBy(orderBy) {
2627
+ if (orderBy === void 0) {
2628
+ return void 0;
2629
+ }
2630
+ if (!isRecord5(orderBy)) {
2631
+ throw new Error("findMany orderBy must be an object");
2632
+ }
2633
+ if ("column" in orderBy) {
2634
+ return {
2635
+ field: normalizeIdentifier(String(orderBy.column), "orderBy column"),
2636
+ direction: orderBy.ascending === false ? "descending" : "ascending"
2637
+ };
2638
+ }
2639
+ const entries = Object.entries(orderBy).filter(([, value]) => value !== void 0);
2640
+ if (entries.length === 0) {
2641
+ return void 0;
2642
+ }
2643
+ if (entries.length > 1) {
2644
+ throw new Error("findMany orderBy only supports a single column in v1");
2645
+ }
2646
+ const [column, input] = entries[0];
2647
+ return {
2648
+ field: normalizeIdentifier(column, "orderBy column"),
2649
+ direction: resolveOrderDirection(input)
2650
+ };
2651
+ }
2652
+
2032
2653
  // src/client.ts
2033
2654
  var DEFAULT_COLUMNS = "*";
2034
- 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;
2035
2655
  var SAFE_CAST_PATTERN = /^[a-z_][a-z0-9_]*(?:\[\])?$/i;
2036
2656
  var ATHENA_NORMALIZED_ERROR_KEY = "__athenaNormalizedError";
2657
+ var QUERY_TRACE_STACK_SKIP_PATTERNS = [
2658
+ "src\\client.ts",
2659
+ "src/client.ts",
2660
+ "dist\\client.",
2661
+ "dist/client.",
2662
+ "node_modules\\@xylex-group\\athena",
2663
+ "node_modules/@xylex-group/athena",
2664
+ "node:internal",
2665
+ "internal/process"
2666
+ ];
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
+ }
2037
2679
  function formatResult(response) {
2038
2680
  const result = {
2039
2681
  data: response.data ?? null,
2040
- error: response.error ?? null,
2682
+ error: null,
2041
2683
  errorDetails: response.errorDetails ?? null,
2042
2684
  status: response.status,
2685
+ statusText: response.statusText ?? null,
2043
2686
  raw: response.raw
2044
2687
  };
2045
2688
  if (response.count !== void 0) {
@@ -2056,22 +2699,239 @@ function attachNormalizedError(result, normalizedError) {
2056
2699
  });
2057
2700
  }
2058
2701
  function createResultFormatter(experimental) {
2059
- if (!experimental?.enableErrorNormalization) {
2060
- return formatResult;
2061
- }
2062
2702
  return (response, context) => {
2063
2703
  const result = formatResult(response);
2064
- if (result.error == null) {
2704
+ if (response.error == null && response.errorDetails == null) {
2065
2705
  return result;
2066
2706
  }
2067
- const normalizedError = normalizeAthenaError(result, context);
2707
+ const normalizedError = normalizeAthenaError(
2708
+ {
2709
+ ...result,
2710
+ error: response.error ?? response.errorDetails?.message ?? null
2711
+ },
2712
+ context
2713
+ );
2714
+ result.error = createResultError(response, result, normalizedError);
2068
2715
  attachNormalizedError(result, normalizedError);
2069
2716
  return result;
2070
2717
  };
2071
2718
  }
2072
- function toSingleResult(response) {
2073
- const payload = response.data;
2074
- const singleData = Array.isArray(payload) ? payload.length ? payload[0] : null : payload ?? null;
2719
+ function isRecord6(value) {
2720
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
2721
+ }
2722
+ function firstNonEmptyString2(...values) {
2723
+ for (const value of values) {
2724
+ if (typeof value === "string" && value.trim().length > 0) {
2725
+ return value.trim();
2726
+ }
2727
+ }
2728
+ return void 0;
2729
+ }
2730
+ function resolveStructuredErrorPayload2(raw) {
2731
+ if (!isRecord6(raw)) return null;
2732
+ return isRecord6(raw.error) ? raw.error : raw;
2733
+ }
2734
+ function resolveStructuredErrorDetails(payload, message) {
2735
+ if (!payload || !("details" in payload)) {
2736
+ return null;
2737
+ }
2738
+ const details = payload.details;
2739
+ if (details == null) {
2740
+ return null;
2741
+ }
2742
+ if (typeof details === "string" && details.trim() === message.trim()) {
2743
+ return null;
2744
+ }
2745
+ return details;
2746
+ }
2747
+ function createResultError(response, result, normalized) {
2748
+ const rawRecord = isRecord6(response.raw) ? response.raw : null;
2749
+ const payload = resolveStructuredErrorPayload2(response.raw);
2750
+ const message = firstNonEmptyString2(
2751
+ response.error,
2752
+ payload?.message,
2753
+ payload?.error,
2754
+ payload?.details,
2755
+ response.errorDetails?.message,
2756
+ normalized.message
2757
+ ) ?? normalized.message;
2758
+ const statusText = firstNonEmptyString2(response.statusText, rawRecord?.statusText) ?? null;
2759
+ const hint = firstNonEmptyString2(payload?.hint, response.errorDetails?.hint) ?? null;
2760
+ const code = firstNonEmptyString2(payload?.code) ?? normalized.code;
2761
+ const details = resolveStructuredErrorDetails(payload, message) ?? response.errorDetails?.cause ?? null;
2762
+ return {
2763
+ message,
2764
+ code,
2765
+ athenaCode: normalized.code,
2766
+ gatewayCode: response.errorDetails?.code ?? null,
2767
+ kind: normalized.kind,
2768
+ category: normalized.category,
2769
+ retryable: normalized.retryable,
2770
+ details,
2771
+ hint,
2772
+ status: result.status,
2773
+ statusText,
2774
+ constraint: normalized.constraint,
2775
+ table: normalized.table,
2776
+ operation: normalized.operation,
2777
+ endpoint: response.errorDetails?.endpoint,
2778
+ method: response.errorDetails?.method,
2779
+ requestId: response.errorDetails?.requestId,
2780
+ cause: response.errorDetails?.cause,
2781
+ raw: result.raw
2782
+ };
2783
+ }
2784
+ function parseQueryTraceCallsiteFrame(frame) {
2785
+ const trimmed = frame.trim();
2786
+ if (!trimmed) {
2787
+ return null;
2788
+ }
2789
+ let body = trimmed.replace(/^at\s+/, "");
2790
+ if (body.startsWith("async ")) {
2791
+ body = body.slice(6);
2792
+ }
2793
+ let functionName;
2794
+ let location = body;
2795
+ const wrappedMatch = body.match(/^(.*?)\s+\((.*)\)$/);
2796
+ if (wrappedMatch) {
2797
+ functionName = wrappedMatch[1].trim() || void 0;
2798
+ location = wrappedMatch[2].trim();
2799
+ }
2800
+ const locationMatch = location.match(/^(.*):(\d+):(\d+)$/);
2801
+ if (!locationMatch) {
2802
+ return null;
2803
+ }
2804
+ const filePath = locationMatch[1].replace(/^file:\/\//, "");
2805
+ const line = Number(locationMatch[2]);
2806
+ const column = Number(locationMatch[3]);
2807
+ if (!Number.isFinite(line) || !Number.isFinite(column)) {
2808
+ return null;
2809
+ }
2810
+ const normalizedPath = filePath.replace(/\\/g, "/");
2811
+ const fileName = normalizedPath.split("/").at(-1) ?? filePath;
2812
+ return {
2813
+ filePath,
2814
+ fileName,
2815
+ line,
2816
+ column,
2817
+ frame: trimmed,
2818
+ functionName
2819
+ };
2820
+ }
2821
+ function captureQueryTraceCallsite() {
2822
+ const stack = new Error().stack;
2823
+ if (!stack) return null;
2824
+ const frames = stack.split("\n").slice(2).map((frame) => frame.trim()).filter(Boolean);
2825
+ for (const frame of frames) {
2826
+ if (QUERY_TRACE_STACK_SKIP_PATTERNS.some((pattern) => frame.includes(pattern))) {
2827
+ continue;
2828
+ }
2829
+ const callsite = parseQueryTraceCallsiteFrame(frame);
2830
+ if (callsite) return callsite;
2831
+ }
2832
+ const fallback = frames.find((frame) => !frame.includes("captureQueryTraceCallsite"));
2833
+ return fallback ? parseQueryTraceCallsiteFrame(fallback) : null;
2834
+ }
2835
+ function defaultQueryTraceLogger(event) {
2836
+ const target = event.table ?? event.functionName ?? "gateway";
2837
+ const outcomeState = event.outcome?.error ? "error" : "ok";
2838
+ const banner = `[athena-js][trace] ${event.operation.toUpperCase()} ${event.endpoint} ${target} ${event.durationMs}ms ${outcomeState}`;
2839
+ console.info(banner, event);
2840
+ }
2841
+ function captureTraceCallsite(tracer) {
2842
+ return tracer?.captureCallsite() ?? null;
2843
+ }
2844
+ function createTraceCallsiteStore(tracer, initialCallsite) {
2845
+ let storedCallsite = initialCallsite ?? void 0;
2846
+ return {
2847
+ resolve(callsite) {
2848
+ if (callsite) {
2849
+ storedCallsite = callsite;
2850
+ return callsite;
2851
+ }
2852
+ if (storedCallsite !== void 0) {
2853
+ return storedCallsite;
2854
+ }
2855
+ const capturedCallsite = captureTraceCallsite(tracer);
2856
+ if (capturedCallsite) {
2857
+ storedCallsite = capturedCallsite;
2858
+ }
2859
+ return capturedCallsite;
2860
+ }
2861
+ };
2862
+ }
2863
+ function createQueryTracer(experimental) {
2864
+ const traceOption = experimental?.traceQueries;
2865
+ if (!traceOption) {
2866
+ return void 0;
2867
+ }
2868
+ const logger = typeof traceOption === "object" && traceOption.logger ? traceOption.logger : defaultQueryTraceLogger;
2869
+ const emit = (event) => {
2870
+ try {
2871
+ logger(event);
2872
+ } catch (error) {
2873
+ console.warn("[athena-js][trace] logger failed", error);
2874
+ }
2875
+ };
2876
+ return {
2877
+ captureCallsite: captureQueryTraceCallsite,
2878
+ publishSuccess(context, result, durationMs, callsite) {
2879
+ emit({
2880
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2881
+ durationMs,
2882
+ operation: context.operation,
2883
+ endpoint: context.endpoint,
2884
+ table: context.table,
2885
+ functionName: context.functionName,
2886
+ sql: context.sql,
2887
+ payload: context.payload,
2888
+ options: context.options,
2889
+ callsite,
2890
+ outcome: {
2891
+ status: result.status,
2892
+ error: result.error,
2893
+ errorDetails: result.errorDetails ?? null,
2894
+ count: result.count ?? null,
2895
+ data: result.data,
2896
+ raw: result.raw
2897
+ }
2898
+ });
2899
+ },
2900
+ publishFailure(context, error, durationMs, callsite) {
2901
+ emit({
2902
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2903
+ durationMs,
2904
+ operation: context.operation,
2905
+ endpoint: context.endpoint,
2906
+ table: context.table,
2907
+ functionName: context.functionName,
2908
+ sql: context.sql,
2909
+ payload: context.payload,
2910
+ options: context.options,
2911
+ callsite,
2912
+ thrownError: error
2913
+ });
2914
+ }
2915
+ };
2916
+ }
2917
+ async function executeWithQueryTrace(tracer, context, runner, callsiteOverride) {
2918
+ if (!tracer) {
2919
+ return runner();
2920
+ }
2921
+ const callsite = callsiteOverride ?? tracer.captureCallsite();
2922
+ const startedAt = Date.now();
2923
+ try {
2924
+ const result = await runner();
2925
+ tracer.publishSuccess(context, result, Date.now() - startedAt, callsite);
2926
+ return result;
2927
+ } catch (error) {
2928
+ tracer.publishFailure(context, error, Date.now() - startedAt, callsite);
2929
+ throw error;
2930
+ }
2931
+ }
2932
+ function toSingleResult(response) {
2933
+ const payload = response.data;
2934
+ const singleData = Array.isArray(payload) ? payload.length ? payload[0] : null : payload ?? null;
2075
2935
  return {
2076
2936
  ...response,
2077
2937
  data: singleData
@@ -2089,15 +2949,16 @@ function asAthenaJsonObject(value) {
2089
2949
  function asAthenaJsonObjectArray(values) {
2090
2950
  return values;
2091
2951
  }
2092
- function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS) {
2952
+ function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS, tracer, initialCallsite) {
2093
2953
  let selectedColumns = defaultColumns === null ? void 0 : defaultColumns;
2094
2954
  let selectedOptions;
2095
2955
  let promise = null;
2096
- const run = (columns, options) => {
2956
+ const callsiteStore = createTraceCallsiteStore(tracer, initialCallsite);
2957
+ const run = (columns, options, callsite) => {
2097
2958
  const payloadColumns = columns ?? selectedColumns;
2098
2959
  const payloadOptions = options ?? selectedOptions;
2099
2960
  if (!promise) {
2100
- promise = executor(payloadColumns, payloadOptions);
2961
+ promise = executor(payloadColumns, payloadOptions, callsiteStore.resolve(callsite));
2101
2962
  }
2102
2963
  return promise;
2103
2964
  };
@@ -2105,7 +2966,7 @@ function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS) {
2105
2966
  select(columns = selectedColumns, options) {
2106
2967
  selectedColumns = columns;
2107
2968
  selectedOptions = options ?? selectedOptions;
2108
- return run(columns, options);
2969
+ return run(columns, options, captureTraceCallsite(tracer));
2109
2970
  },
2110
2971
  returning(columns = selectedColumns, options) {
2111
2972
  return mutationQuery.select(columns, options);
@@ -2113,7 +2974,7 @@ function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS) {
2113
2974
  single(columns = selectedColumns, options) {
2114
2975
  selectedColumns = columns;
2115
2976
  selectedOptions = options ?? selectedOptions;
2116
- return run(columns, options).then(toSingleResult);
2977
+ return run(columns, options, captureTraceCallsite(tracer)).then(toSingleResult);
2117
2978
  },
2118
2979
  maybeSingle(columns = selectedColumns, options) {
2119
2980
  return mutationQuery.single(columns, options);
@@ -2136,21 +2997,12 @@ function getResourceId(state) {
2136
2997
  );
2137
2998
  return candidate?.value?.toString();
2138
2999
  }
2139
- function stringifyFilterValue(value) {
3000
+ function stringifyFilterValue2(value) {
2140
3001
  if (Array.isArray(value)) {
2141
3002
  return value.join(",");
2142
3003
  }
2143
3004
  return String(value);
2144
3005
  }
2145
- function isUuidString(value) {
2146
- return UUID_PATTERN.test(value.trim());
2147
- }
2148
- function isUuidIdentifierColumn(column) {
2149
- return column === "id" || /(?:^|_)uuid(?:_|$)/i.test(column) || /_id$/i.test(column);
2150
- }
2151
- function shouldUseUuidTextComparison(column, value) {
2152
- return typeof value === "string" && isUuidString(value) && isUuidIdentifierColumn(column);
2153
- }
2154
3006
  function normalizeCast(cast) {
2155
3007
  const normalized = cast.trim().toLowerCase();
2156
3008
  if (!SAFE_CAST_PATTERN.test(normalized)) {
@@ -2173,25 +3025,92 @@ function withCast(expression, cast) {
2173
3025
  }
2174
3026
  function buildSelectColumnsClause(columns) {
2175
3027
  if (Array.isArray(columns)) {
2176
- return columns.map((column) => quoteQualifiedIdentifier(column)).join(", ");
3028
+ return columns.map((column) => quoteSelectColumnToken(column)).join(", ");
2177
3029
  }
2178
3030
  return quoteSelectColumnsExpression(columns);
2179
3031
  }
3032
+ function parseIdentifierSegment(input) {
3033
+ const trimmed = input.trim();
3034
+ if (!trimmed) return null;
3035
+ if (!trimmed.startsWith('"')) {
3036
+ return {
3037
+ normalizedValue: trimmed.toLowerCase()
3038
+ };
3039
+ }
3040
+ let value = "";
3041
+ let index = 1;
3042
+ let closed = false;
3043
+ while (index < trimmed.length) {
3044
+ const char = trimmed[index];
3045
+ const next = index + 1 < trimmed.length ? trimmed[index + 1] : "";
3046
+ if (char === '"' && next === '"') {
3047
+ value += '"';
3048
+ index += 2;
3049
+ continue;
3050
+ }
3051
+ if (char === '"') {
3052
+ closed = true;
3053
+ index += 1;
3054
+ break;
3055
+ }
3056
+ value += char;
3057
+ index += 1;
3058
+ }
3059
+ if (!closed || trimmed.slice(index).trim().length > 0 || !value.trim()) {
3060
+ return null;
3061
+ }
3062
+ return {
3063
+ normalizedValue: value
3064
+ };
3065
+ }
3066
+ function splitQualifiedTableName(tableName) {
3067
+ const trimmed = tableName.trim();
3068
+ let inQuotes = false;
3069
+ for (let index = 0; index < trimmed.length; index += 1) {
3070
+ const char = trimmed[index];
3071
+ const next = index + 1 < trimmed.length ? trimmed[index + 1] : "";
3072
+ if (char === '"') {
3073
+ if (inQuotes && next === '"') {
3074
+ index += 1;
3075
+ continue;
3076
+ }
3077
+ inQuotes = !inQuotes;
3078
+ continue;
3079
+ }
3080
+ if (char === "." && !inQuotes) {
3081
+ const schemaSegment = trimmed.slice(0, index).trim();
3082
+ const tableSegment = trimmed.slice(index + 1).trim();
3083
+ if (!schemaSegment || !tableSegment) {
3084
+ return null;
3085
+ }
3086
+ return { schemaSegment };
3087
+ }
3088
+ }
3089
+ return null;
3090
+ }
2180
3091
  function resolveTableNameForCall(tableName, schema) {
2181
3092
  if (!schema) return tableName;
2182
3093
  const normalizedSchema = schema.trim();
2183
3094
  if (!normalizedSchema) {
2184
3095
  throw new Error("schema option must be a non-empty string");
2185
3096
  }
2186
- if (tableName.includes(".")) {
2187
- if (tableName.startsWith(`${normalizedSchema}.`)) {
2188
- return tableName;
3097
+ const normalizedTableName = tableName.trim();
3098
+ const parsedSchema = parseIdentifierSegment(normalizedSchema);
3099
+ if (!parsedSchema) {
3100
+ throw new Error("schema option must be a non-empty string");
3101
+ }
3102
+ const qualified = splitQualifiedTableName(normalizedTableName);
3103
+ if (qualified) {
3104
+ const parsedTableSchema = parseIdentifierSegment(qualified.schemaSegment);
3105
+ const sameSchema = parsedTableSchema ? parsedTableSchema.normalizedValue === parsedSchema.normalizedValue : normalizedTableName.startsWith(`${normalizedSchema}.`);
3106
+ if (sameSchema) {
3107
+ return normalizedTableName;
2189
3108
  }
2190
3109
  throw new Error(
2191
- `schema option "${normalizedSchema}" conflicts with schema-qualified table "${tableName}"`
3110
+ `schema option "${normalizedSchema}" conflicts with schema-qualified table "${normalizedTableName}"`
2192
3111
  );
2193
3112
  }
2194
- return `${normalizedSchema}.${tableName}`;
3113
+ return `${normalizedSchema}.${normalizedTableName}`;
2195
3114
  }
2196
3115
  function conditionToSqlClause(condition) {
2197
3116
  if (!condition.column) return null;
@@ -2269,6 +3188,237 @@ function buildTypedSelectQuery(input) {
2269
3188
  }
2270
3189
  return `${sqlParts.join(" ")};`;
2271
3190
  }
3191
+ function sanitizeSqlComment(comment) {
3192
+ return comment.replace(/\*\//g, "* /");
3193
+ }
3194
+ function toSqlJsonLiteral(value) {
3195
+ if (value === void 0) return "DEFAULT";
3196
+ if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
3197
+ return toSqlLiteral(value);
3198
+ }
3199
+ return `'${escapeSqlStringLiteral(JSON.stringify(value))}'::jsonb`;
3200
+ }
3201
+ function conditionToDebugSqlClause(condition) {
3202
+ const exact = conditionToSqlClause(condition);
3203
+ if (exact) return exact;
3204
+ const rawCondition = sanitizeSqlComment(JSON.stringify(condition));
3205
+ if (!condition.column) {
3206
+ return `TRUE /* unsupported condition: ${rawCondition} */`;
3207
+ }
3208
+ const column = withCast(quoteQualifiedIdentifier(condition.column), condition.column_cast);
3209
+ const value = condition.value;
3210
+ const rhs = withCast(toSqlJsonLiteral(value), condition.value_cast);
3211
+ switch (condition.operator) {
3212
+ case "contains":
3213
+ return `${column} @> ${rhs}`;
3214
+ case "containedBy":
3215
+ return `${column} <@ ${rhs}`;
3216
+ case "not":
3217
+ return `TRUE /* NOT expression passthrough: ${rawCondition} */`;
3218
+ case "or":
3219
+ return `TRUE /* OR expression passthrough: ${rawCondition} */`;
3220
+ default:
3221
+ return `TRUE /* unsupported condition: ${rawCondition} */`;
3222
+ }
3223
+ }
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
+ function appendOrderLimitOffset(sqlParts, order, limit, offset) {
3236
+ if (order?.field) {
3237
+ const direction = order.direction === "descending" ? "DESC" : "ASC";
3238
+ sqlParts.push(`ORDER BY ${quoteQualifiedIdentifier(order.field)} ${direction}`);
3239
+ }
3240
+ if (limit !== void 0) {
3241
+ sqlParts.push(`LIMIT ${Math.max(0, Math.trunc(limit))}`);
3242
+ }
3243
+ if (offset !== void 0) {
3244
+ sqlParts.push(`OFFSET ${Math.max(0, Math.trunc(offset))}`);
3245
+ }
3246
+ }
3247
+ function buildDebugSelectQuery(input) {
3248
+ const sqlParts = [
3249
+ `SELECT ${buildSelectColumnsClause(input.columns)} FROM ${quoteQualifiedIdentifier(input.tableName)}`
3250
+ ];
3251
+ if (input.conditions?.length) {
3252
+ const whereClauses = input.conditions.map(conditionToDebugSqlClause);
3253
+ sqlParts.push(`WHERE ${whereClauses.join(" AND ")}`);
3254
+ }
3255
+ const pagination = resolvePagination(input);
3256
+ appendOrderLimitOffset(sqlParts, input.order, pagination.limit, pagination.offset);
3257
+ return `${sqlParts.join(" ")};`;
3258
+ }
3259
+ function resolveDebugTableIdentifier(tableName) {
3260
+ if (!tableName?.trim()) {
3261
+ return '"__unknown_table__"';
3262
+ }
3263
+ return quoteQualifiedIdentifier(tableName);
3264
+ }
3265
+ function buildInsertDebugSql(payload) {
3266
+ const rows = Array.isArray(payload.insert_body) ? payload.insert_body : [payload.insert_body];
3267
+ const columns = [];
3268
+ const seen = /* @__PURE__ */ new Set();
3269
+ for (const row of rows) {
3270
+ for (const column of Object.keys(row)) {
3271
+ if (seen.has(column)) continue;
3272
+ seen.add(column);
3273
+ columns.push(column);
3274
+ }
3275
+ }
3276
+ const sqlParts = [`INSERT INTO ${quoteQualifiedIdentifier(payload.table_name)}`];
3277
+ if (!rows.length || !columns.length) {
3278
+ sqlParts.push("DEFAULT VALUES");
3279
+ if (rows.length > 1) {
3280
+ sqlParts.push(`/* trace: ${rows.length} rows collapsed to DEFAULT VALUES */`);
3281
+ }
3282
+ } else {
3283
+ const valuesClause = rows.map((row) => {
3284
+ const values = columns.map((column) => {
3285
+ const hasColumn = Object.prototype.hasOwnProperty.call(row, column);
3286
+ if (!hasColumn) {
3287
+ return payload.default_to_null ? "NULL" : "DEFAULT";
3288
+ }
3289
+ const rowValue = row[column];
3290
+ return toSqlJsonLiteral(rowValue);
3291
+ });
3292
+ return `(${values.join(", ")})`;
3293
+ }).join(", ");
3294
+ const columnClause = columns.map((column) => quoteQualifiedIdentifier(column)).join(", ");
3295
+ sqlParts.push(`(${columnClause})`);
3296
+ sqlParts.push(`VALUES ${valuesClause}`);
3297
+ }
3298
+ if (payload.on_conflict) {
3299
+ const conflictColumns = Array.isArray(payload.on_conflict) ? payload.on_conflict.map((column) => quoteQualifiedIdentifier(column)).join(", ") : payload.on_conflict;
3300
+ if (payload.update_body && Object.keys(payload.update_body).length > 0) {
3301
+ const assignments = Object.entries(payload.update_body).map(
3302
+ ([column, value]) => `${quoteQualifiedIdentifier(column)} = ${toSqlJsonLiteral(value)}`
3303
+ );
3304
+ sqlParts.push(`ON CONFLICT (${conflictColumns}) DO UPDATE SET ${assignments.join(", ")}`);
3305
+ } else {
3306
+ sqlParts.push(`ON CONFLICT (${conflictColumns}) DO NOTHING`);
3307
+ }
3308
+ }
3309
+ if (payload.columns) {
3310
+ sqlParts.push(`RETURNING ${buildSelectColumnsClause(payload.columns)}`);
3311
+ }
3312
+ return `${sqlParts.join(" ")};`;
3313
+ }
3314
+ function buildUpdateDebugSql(payload) {
3315
+ const set = payload.set ?? payload.data ?? {};
3316
+ const assignments = Object.entries(set).map(
3317
+ ([column, value]) => `${quoteQualifiedIdentifier(column)} = ${toSqlJsonLiteral(value)}`
3318
+ );
3319
+ const sqlParts = [
3320
+ `UPDATE ${resolveDebugTableIdentifier(payload.table_name)} SET ${assignments.length ? assignments.join(", ") : "/* empty set */"}`
3321
+ ];
3322
+ if (payload.conditions?.length) {
3323
+ const whereClauses = payload.conditions.map(conditionToDebugSqlClause);
3324
+ sqlParts.push(`WHERE ${whereClauses.join(" AND ")}`);
3325
+ }
3326
+ const pagination = resolvePagination({
3327
+ currentPage: payload.current_page,
3328
+ pageSize: payload.page_size
3329
+ });
3330
+ appendOrderLimitOffset(sqlParts, payload.sort_by, pagination.limit, pagination.offset);
3331
+ if (payload.columns) {
3332
+ sqlParts.push(`RETURNING ${buildSelectColumnsClause(payload.columns)}`);
3333
+ }
3334
+ return `${sqlParts.join(" ")};`;
3335
+ }
3336
+ function buildDeleteDebugSql(payload) {
3337
+ const sqlParts = [`DELETE FROM ${quoteQualifiedIdentifier(payload.table_name)}`];
3338
+ const whereClauses = [];
3339
+ if (payload.resource_id) {
3340
+ whereClauses.push(`"resource_id" = ${toSqlLiteral(payload.resource_id)}`);
3341
+ }
3342
+ if (payload.conditions?.length) {
3343
+ whereClauses.push(...payload.conditions.map(conditionToDebugSqlClause));
3344
+ }
3345
+ if (whereClauses.length) {
3346
+ sqlParts.push(`WHERE ${whereClauses.join(" AND ")}`);
3347
+ }
3348
+ const pagination = resolvePagination({
3349
+ currentPage: payload.current_page,
3350
+ pageSize: payload.page_size
3351
+ });
3352
+ appendOrderLimitOffset(sqlParts, payload.sort_by, pagination.limit, pagination.offset);
3353
+ if (payload.columns) {
3354
+ sqlParts.push(`RETURNING ${buildSelectColumnsClause(payload.columns)}`);
3355
+ }
3356
+ return `${sqlParts.join(" ")};`;
3357
+ }
3358
+ function rpcFilterToSqlClause(filter) {
3359
+ const column = quoteQualifiedIdentifier(filter.column);
3360
+ const value = filter.value;
3361
+ switch (filter.operator) {
3362
+ case "eq":
3363
+ case "neq":
3364
+ case "gt":
3365
+ case "gte":
3366
+ case "lt":
3367
+ case "lte":
3368
+ case "like":
3369
+ case "ilike": {
3370
+ if (value === void 0 || Array.isArray(value)) {
3371
+ return `TRUE /* unsupported rpc filter: ${sanitizeSqlComment(JSON.stringify(filter))} */`;
3372
+ }
3373
+ const operatorMap = {
3374
+ eq: "=",
3375
+ neq: "!=",
3376
+ gt: ">",
3377
+ gte: ">=",
3378
+ lt: "<",
3379
+ lte: "<=",
3380
+ like: "LIKE",
3381
+ ilike: "ILIKE"
3382
+ };
3383
+ return `${column} ${operatorMap[filter.operator]} ${toSqlLiteral(value)}`;
3384
+ }
3385
+ case "is":
3386
+ if (value === null) return `${column} IS NULL`;
3387
+ if (value === true) return `${column} IS TRUE`;
3388
+ if (value === false) return `${column} IS FALSE`;
3389
+ return `TRUE /* unsupported rpc filter: ${sanitizeSqlComment(JSON.stringify(filter))} */`;
3390
+ case "in":
3391
+ if (!Array.isArray(value)) {
3392
+ return `TRUE /* unsupported rpc filter: ${sanitizeSqlComment(JSON.stringify(filter))} */`;
3393
+ }
3394
+ if (value.length === 0) return "FALSE";
3395
+ return `${column} IN (${value.map((item) => toSqlLiteral(item)).join(", ")})`;
3396
+ default:
3397
+ return `TRUE /* unsupported rpc filter: ${sanitizeSqlComment(JSON.stringify(filter))} */`;
3398
+ }
3399
+ }
3400
+ function buildRpcDebugSql(payload) {
3401
+ const argsEntries = payload.args ? Object.entries(payload.args) : [];
3402
+ const argsClause = argsEntries.map(([key, value]) => `${quoteQualifiedIdentifier(key)} => ${toSqlJsonLiteral(value)}`).join(", ");
3403
+ const functionRef = payload.schema ? `${quoteQualifiedIdentifier(payload.schema)}.${quoteQualifiedIdentifier(payload.function)}` : quoteQualifiedIdentifier(payload.function);
3404
+ const sqlParts = [
3405
+ `SELECT ${payload.select ? quoteSelectColumnsExpression(payload.select) : "*"} FROM ${functionRef}(${argsClause})`
3406
+ ];
3407
+ if (payload.filters?.length) {
3408
+ sqlParts.push(`WHERE ${payload.filters.map(rpcFilterToSqlClause).join(" AND ")}`);
3409
+ }
3410
+ if (payload.order?.column) {
3411
+ const direction = payload.order.ascending === false ? "DESC" : "ASC";
3412
+ sqlParts.push(`ORDER BY ${quoteQualifiedIdentifier(payload.order.column)} ${direction}`);
3413
+ }
3414
+ if (payload.limit !== void 0) {
3415
+ sqlParts.push(`LIMIT ${Math.max(0, Math.trunc(payload.limit))}`);
3416
+ }
3417
+ if (payload.offset !== void 0) {
3418
+ sqlParts.push(`OFFSET ${Math.max(0, Math.trunc(payload.offset))}`);
3419
+ }
3420
+ return `${sqlParts.join(" ")};`;
3421
+ }
2272
3422
  function createFilterMethods(state, addCondition, self) {
2273
3423
  return {
2274
3424
  eq(column, value) {
@@ -2380,7 +3530,7 @@ function createFilterMethods(state, addCondition, self) {
2380
3530
  not(columnOrExpression, operator, value) {
2381
3531
  const expression = String(columnOrExpression);
2382
3532
  if (operator != null && value !== void 0) {
2383
- addCondition("not", void 0, `${expression}.${operator}.${stringifyFilterValue(value)}`);
3533
+ addCondition("not", void 0, `${expression}.${operator}.${stringifyFilterValue2(value)}`);
2384
3534
  } else {
2385
3535
  addCondition("not", void 0, expression);
2386
3536
  }
@@ -2443,14 +3593,15 @@ function createRpcFilterMethods(filters, self) {
2443
3593
  }
2444
3594
  };
2445
3595
  }
2446
- function createRpcBuilder(functionName, args, baseOptions, client, formatGatewayResult) {
3596
+ function createRpcBuilder(functionName, args, baseOptions, client, formatGatewayResult, tracer, initialCallsite) {
2447
3597
  const state = {
2448
3598
  filters: []
2449
3599
  };
2450
3600
  let selectedColumns;
2451
3601
  let selectedOptions;
2452
3602
  let promise = null;
2453
- const executeRpc = async (columns, options) => {
3603
+ const callsiteStore = createTraceCallsiteStore(tracer, initialCallsite);
3604
+ const executeRpc = async (columns, options, callsite) => {
2454
3605
  const mergedOptions = mergeOptions(baseOptions, options);
2455
3606
  const payload = {
2456
3607
  function: functionName,
@@ -2464,14 +3615,30 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
2464
3615
  offset: state.offset,
2465
3616
  order: state.order
2466
3617
  };
2467
- const response = await client.rpcGateway(payload, mergedOptions);
2468
- return formatGatewayResult(response, { operation: "rpc" });
3618
+ const endpoint = mergedOptions?.get ? `/rpc/${functionName}` : "/gateway/rpc";
3619
+ const sql = buildRpcDebugSql(payload);
3620
+ return executeWithQueryTrace(
3621
+ tracer,
3622
+ {
3623
+ operation: "rpc",
3624
+ endpoint,
3625
+ functionName,
3626
+ sql,
3627
+ payload,
3628
+ options: mergedOptions
3629
+ },
3630
+ async () => {
3631
+ const response = await client.rpcGateway(payload, mergedOptions);
3632
+ return formatGatewayResult(response, { operation: "rpc" });
3633
+ },
3634
+ callsite
3635
+ );
2469
3636
  };
2470
- const run = (columns, options) => {
3637
+ const run = (columns, options, callsite) => {
2471
3638
  const payloadColumns = columns ?? selectedColumns;
2472
3639
  const payloadOptions = options ?? selectedOptions;
2473
3640
  if (!promise) {
2474
- promise = executeRpc(payloadColumns, payloadOptions);
3641
+ promise = executeRpc(payloadColumns, payloadOptions, callsiteStore.resolve(callsite));
2475
3642
  }
2476
3643
  return promise;
2477
3644
  };
@@ -2481,10 +3648,10 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
2481
3648
  select(columns = selectedColumns, options) {
2482
3649
  selectedColumns = columns;
2483
3650
  selectedOptions = options ?? selectedOptions;
2484
- return run(columns, options);
3651
+ return run(columns, options, captureTraceCallsite(tracer));
2485
3652
  },
2486
3653
  async single(columns, options) {
2487
- const result = await run(columns, options);
3654
+ const result = await run(columns, options, captureTraceCallsite(tracer));
2488
3655
  return toSingleResult(result);
2489
3656
  },
2490
3657
  maybeSingle(columns, options) {
@@ -2519,7 +3686,7 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
2519
3686
  });
2520
3687
  return builder;
2521
3688
  }
2522
- function createTableBuilder(tableName, client, formatGatewayResult) {
3689
+ function createTableBuilder(tableName, client, formatGatewayResult, tracer, experimental) {
2523
3690
  const state = {
2524
3691
  conditions: []
2525
3692
  };
@@ -2551,15 +3718,24 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
2551
3718
  }
2552
3719
  state.conditions.push(condition);
2553
3720
  };
3721
+ const snapshotState = () => ({
3722
+ conditions: state.conditions.map((condition) => ({ ...condition })),
3723
+ limit: state.limit,
3724
+ offset: state.offset,
3725
+ order: state.order ? { ...state.order } : void 0,
3726
+ currentPage: state.currentPage,
3727
+ pageSize: state.pageSize,
3728
+ totalPages: state.totalPages
3729
+ });
2554
3730
  const builder = {};
2555
3731
  const filterMethods = createFilterMethods(
2556
3732
  state,
2557
3733
  addCondition,
2558
3734
  builder
2559
3735
  );
2560
- const runSelect = async (columns = DEFAULT_COLUMNS, options) => {
3736
+ const runSelect = async (columns = DEFAULT_COLUMNS, options, executionState = snapshotState(), callsite) => {
2561
3737
  const resolvedTableName = resolveTableNameForCall(tableName, options?.schema);
2562
- const conditions = state.conditions.length ? state.conditions.map((condition) => ({ ...condition })) : void 0;
3738
+ const conditions = executionState.conditions.length ? executionState.conditions.map((condition) => ({ ...condition })) : void 0;
2563
3739
  const hasTypedEqualityComparison = conditions?.some(
2564
3740
  (condition) => condition.operator === "eq" && (condition.value_cast !== void 0 || condition.column_cast !== void 0)
2565
3741
  ) ?? false;
@@ -2568,53 +3744,107 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
2568
3744
  tableName: resolvedTableName,
2569
3745
  columns,
2570
3746
  conditions,
2571
- limit: state.limit,
2572
- offset: state.offset,
2573
- currentPage: state.currentPage,
2574
- pageSize: state.pageSize,
2575
- order: state.order
3747
+ limit: executionState.limit,
3748
+ offset: executionState.offset,
3749
+ currentPage: executionState.currentPage,
3750
+ pageSize: executionState.pageSize,
3751
+ order: executionState.order
2576
3752
  });
2577
3753
  if (query) {
2578
- const queryResponse = await client.queryGateway({ query }, options);
2579
- return formatGatewayResult(queryResponse, { table: resolvedTableName, operation: "select" });
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
+ );
2580
3771
  }
2581
3772
  }
2582
3773
  const payload = {
2583
3774
  table_name: resolvedTableName,
2584
3775
  columns,
2585
3776
  conditions,
2586
- limit: state.limit,
2587
- offset: state.offset,
2588
- current_page: state.currentPage,
2589
- page_size: state.pageSize,
2590
- total_pages: state.totalPages,
2591
- sort_by: state.order,
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,
2592
3783
  strip_nulls: options?.stripNulls ?? true,
2593
3784
  count: options?.count,
2594
3785
  head: options?.head
2595
3786
  };
2596
- const response = await client.fetchGateway(payload, options);
2597
- return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
3787
+ const sql = buildDebugSelectQuery({
3788
+ 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
3796
+ });
3797
+ return executeWithQueryTrace(
3798
+ tracer,
3799
+ {
3800
+ operation: "select",
3801
+ endpoint: "/gateway/fetch",
3802
+ table: resolvedTableName,
3803
+ sql,
3804
+ payload,
3805
+ options
3806
+ },
3807
+ async () => {
3808
+ const response = await client.fetchGateway(payload, options);
3809
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
3810
+ },
3811
+ callsite
3812
+ );
2598
3813
  };
2599
- const createSelectChain = (columns, options) => {
3814
+ const createSelectChain = (columns, options, initialCallsite) => {
2600
3815
  const chain = {};
3816
+ const callsiteStore = createTraceCallsiteStore(tracer, initialCallsite);
2601
3817
  const filterMethods2 = createFilterMethods(state, addCondition, chain);
2602
3818
  Object.assign(chain, filterMethods2, {
2603
3819
  async single(cols, opts) {
2604
- const r = await runSelect(cols ?? columns, opts ?? options);
3820
+ const r = await runSelect(
3821
+ cols ?? columns,
3822
+ opts ?? options,
3823
+ snapshotState(),
3824
+ callsiteStore.resolve(captureTraceCallsite(tracer))
3825
+ );
2605
3826
  return toSingleResult(r);
2606
3827
  },
2607
3828
  maybeSingle(cols, opts) {
2608
3829
  return chain.single(cols, opts);
2609
3830
  },
2610
3831
  then(onfulfilled, onrejected) {
2611
- return runSelect(columns, options).then(onfulfilled, onrejected);
3832
+ return runSelect(
3833
+ columns,
3834
+ options,
3835
+ snapshotState(),
3836
+ callsiteStore.resolve()
3837
+ ).then(onfulfilled, onrejected);
2612
3838
  },
2613
3839
  catch(onrejected) {
2614
- return runSelect(columns, options).catch(onrejected);
3840
+ return runSelect(columns, options, snapshotState(), callsiteStore.resolve()).catch(
3841
+ onrejected
3842
+ );
2615
3843
  },
2616
3844
  finally(onfinally) {
2617
- return runSelect(columns, options).finally(onfinally);
3845
+ return runSelect(columns, options, snapshotState(), callsiteStore.resolve()).finally(
3846
+ onfinally
3847
+ );
2618
3848
  }
2619
3849
  });
2620
3850
  return chain;
@@ -2631,11 +3861,75 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
2631
3861
  return builder;
2632
3862
  },
2633
3863
  select(columns = DEFAULT_COLUMNS, options) {
2634
- return createSelectChain(columns, options);
3864
+ return createSelectChain(columns, options, captureTraceCallsite(tracer));
3865
+ },
3866
+ async findMany(options) {
3867
+ const columns = compileSelectShape(options.select);
3868
+ const baseState = snapshotState();
3869
+ const executionState = snapshotState();
3870
+ const callsite = captureTraceCallsite(tracer);
3871
+ const compiledWhere = compileWhere(options.where);
3872
+ if (compiledWhere?.length) {
3873
+ executionState.conditions.push(...compiledWhere);
3874
+ }
3875
+ if (options.orderBy !== void 0) {
3876
+ executionState.order = compileOrderBy(options.orderBy);
3877
+ }
3878
+ if (options.limit !== void 0) {
3879
+ executionState.limit = options.limit;
3880
+ }
3881
+ if (experimental?.findManyAst && canUseFindManyAstTransport(baseState)) {
3882
+ const resolvedTableName = resolveTableNameForCall(tableName, void 0);
3883
+ const payload = {
3884
+ table_name: resolvedTableName,
3885
+ select: options.select
3886
+ };
3887
+ if (options.where !== void 0) {
3888
+ payload.where = options.where;
3889
+ }
3890
+ const astOrder = toFindManyAstOrder(executionState.order);
3891
+ if (astOrder !== void 0) {
3892
+ payload.orderBy = astOrder;
3893
+ }
3894
+ if (executionState.limit !== void 0) {
3895
+ payload.limit = executionState.limit;
3896
+ }
3897
+ const sql = buildDebugSelectQuery({
3898
+ tableName: resolvedTableName,
3899
+ columns,
3900
+ conditions: executionState.conditions,
3901
+ limit: executionState.limit,
3902
+ order: executionState.order
3903
+ });
3904
+ return executeWithQueryTrace(
3905
+ tracer,
3906
+ {
3907
+ operation: "select",
3908
+ endpoint: "/gateway/fetch",
3909
+ table: resolvedTableName,
3910
+ sql,
3911
+ payload
3912
+ },
3913
+ async () => {
3914
+ const response = await client.fetchGateway(
3915
+ payload
3916
+ );
3917
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
3918
+ },
3919
+ callsite
3920
+ );
3921
+ }
3922
+ return runSelect(
3923
+ columns,
3924
+ void 0,
3925
+ executionState,
3926
+ callsite
3927
+ );
2635
3928
  },
2636
3929
  insert(values, options) {
3930
+ const mutationCallsite = captureTraceCallsite(tracer);
2637
3931
  if (Array.isArray(values)) {
2638
- const executeInsertMany = async (columns, selectOptions) => {
3932
+ const executeInsertMany = async (columns, selectOptions, callsite) => {
2639
3933
  const mergedOptions = mergeOptions(options, selectOptions);
2640
3934
  const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
2641
3935
  const payload = {
@@ -2648,12 +3942,27 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
2648
3942
  if (mergedOptions?.defaultToNull !== void 0) {
2649
3943
  payload.default_to_null = mergedOptions.defaultToNull;
2650
3944
  }
2651
- const response = await client.insertGateway(payload, mergedOptions);
2652
- return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
3945
+ const sql = buildInsertDebugSql(payload);
3946
+ return executeWithQueryTrace(
3947
+ tracer,
3948
+ {
3949
+ operation: "insert",
3950
+ endpoint: "/gateway/insert",
3951
+ table: resolvedTableName,
3952
+ sql,
3953
+ payload,
3954
+ options: mergedOptions
3955
+ },
3956
+ async () => {
3957
+ const response = await client.insertGateway(payload, mergedOptions);
3958
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
3959
+ },
3960
+ callsite
3961
+ );
2653
3962
  };
2654
- return createMutationQuery(executeInsertMany);
3963
+ return createMutationQuery(executeInsertMany, DEFAULT_COLUMNS, tracer, mutationCallsite);
2655
3964
  }
2656
- const executeInsertOne = async (columns, selectOptions) => {
3965
+ const executeInsertOne = async (columns, selectOptions, callsite) => {
2657
3966
  const mergedOptions = mergeOptions(options, selectOptions);
2658
3967
  const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
2659
3968
  const payload = {
@@ -2666,14 +3975,30 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
2666
3975
  if (mergedOptions?.defaultToNull !== void 0) {
2667
3976
  payload.default_to_null = mergedOptions.defaultToNull;
2668
3977
  }
2669
- const response = await client.insertGateway(payload, mergedOptions);
2670
- return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
3978
+ const sql = buildInsertDebugSql(payload);
3979
+ return executeWithQueryTrace(
3980
+ tracer,
3981
+ {
3982
+ operation: "insert",
3983
+ endpoint: "/gateway/insert",
3984
+ table: resolvedTableName,
3985
+ sql,
3986
+ payload,
3987
+ options: mergedOptions
3988
+ },
3989
+ async () => {
3990
+ const response = await client.insertGateway(payload, mergedOptions);
3991
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
3992
+ },
3993
+ callsite
3994
+ );
2671
3995
  };
2672
- return createMutationQuery(executeInsertOne);
3996
+ return createMutationQuery(executeInsertOne, DEFAULT_COLUMNS, tracer, mutationCallsite);
2673
3997
  },
2674
3998
  upsert(values, options) {
3999
+ const mutationCallsite = captureTraceCallsite(tracer);
2675
4000
  if (Array.isArray(values)) {
2676
- const executeUpsertMany = async (columns, selectOptions) => {
4001
+ const executeUpsertMany = async (columns, selectOptions, callsite) => {
2677
4002
  const mergedOptions = mergeOptions(options, selectOptions);
2678
4003
  const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
2679
4004
  const payload = {
@@ -2688,12 +4013,27 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
2688
4013
  if (mergedOptions?.defaultToNull !== void 0) {
2689
4014
  payload.default_to_null = mergedOptions.defaultToNull;
2690
4015
  }
2691
- const response = await client.insertGateway(payload, mergedOptions);
2692
- return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
4016
+ const sql = buildInsertDebugSql(payload);
4017
+ return executeWithQueryTrace(
4018
+ tracer,
4019
+ {
4020
+ operation: "upsert",
4021
+ endpoint: "/gateway/insert",
4022
+ table: resolvedTableName,
4023
+ sql,
4024
+ payload,
4025
+ options: mergedOptions
4026
+ },
4027
+ async () => {
4028
+ const response = await client.insertGateway(payload, mergedOptions);
4029
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
4030
+ },
4031
+ callsite
4032
+ );
2693
4033
  };
2694
- return createMutationQuery(executeUpsertMany);
4034
+ return createMutationQuery(executeUpsertMany, DEFAULT_COLUMNS, tracer, mutationCallsite);
2695
4035
  }
2696
- const executeUpsertOne = async (columns, selectOptions) => {
4036
+ const executeUpsertOne = async (columns, selectOptions, callsite) => {
2697
4037
  const mergedOptions = mergeOptions(options, selectOptions);
2698
4038
  const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
2699
4039
  const payload = {
@@ -2708,13 +4048,29 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
2708
4048
  if (mergedOptions?.defaultToNull !== void 0) {
2709
4049
  payload.default_to_null = mergedOptions.defaultToNull;
2710
4050
  }
2711
- const response = await client.insertGateway(payload, mergedOptions);
2712
- return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
4051
+ const sql = buildInsertDebugSql(payload);
4052
+ return executeWithQueryTrace(
4053
+ tracer,
4054
+ {
4055
+ operation: "upsert",
4056
+ endpoint: "/gateway/insert",
4057
+ table: resolvedTableName,
4058
+ sql,
4059
+ payload,
4060
+ options: mergedOptions
4061
+ },
4062
+ async () => {
4063
+ const response = await client.insertGateway(payload, mergedOptions);
4064
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
4065
+ },
4066
+ callsite
4067
+ );
2713
4068
  };
2714
- return createMutationQuery(executeUpsertOne);
4069
+ return createMutationQuery(executeUpsertOne, DEFAULT_COLUMNS, tracer, mutationCallsite);
2715
4070
  },
2716
4071
  update(values, options) {
2717
- const executeUpdate = async (columns, selectOptions) => {
4072
+ const mutationCallsite = captureTraceCallsite(tracer);
4073
+ const executeUpdate = async (columns, selectOptions, callsite) => {
2718
4074
  const filters = state.conditions.length ? [...state.conditions] : void 0;
2719
4075
  const mergedOptions = mergeOptions(options, selectOptions);
2720
4076
  const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
@@ -2729,10 +4085,25 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
2729
4085
  if (state.pageSize !== void 0) payload.page_size = state.pageSize;
2730
4086
  if (state.totalPages !== void 0) payload.total_pages = state.totalPages;
2731
4087
  if (columns) payload.columns = columns;
2732
- const response = await client.updateGateway(payload, mergedOptions);
2733
- return formatGatewayResult(response, { table: resolvedTableName, operation: "update" });
4088
+ const sql = buildUpdateDebugSql(payload);
4089
+ return executeWithQueryTrace(
4090
+ tracer,
4091
+ {
4092
+ operation: "update",
4093
+ endpoint: "/gateway/update",
4094
+ table: resolvedTableName,
4095
+ sql,
4096
+ payload,
4097
+ options: mergedOptions
4098
+ },
4099
+ async () => {
4100
+ const response = await client.updateGateway(payload, mergedOptions);
4101
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "update" });
4102
+ },
4103
+ callsite
4104
+ );
2734
4105
  };
2735
- const mutation = createMutationQuery(executeUpdate, null);
4106
+ const mutation = createMutationQuery(executeUpdate, null, tracer, mutationCallsite);
2736
4107
  const updateChain = {};
2737
4108
  const filterMethods2 = createFilterMethods(state, addCondition, updateChain);
2738
4109
  Object.assign(updateChain, filterMethods2, mutation);
@@ -2744,7 +4115,8 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
2744
4115
  if (!resourceId && !filters?.length) {
2745
4116
  throw new Error('delete requires a resource_id either via eq("resource_id", ...) or options.resourceId');
2746
4117
  }
2747
- const executeDelete = async (columns, selectOptions) => {
4118
+ const mutationCallsite = captureTraceCallsite(tracer);
4119
+ const executeDelete = async (columns, selectOptions, callsite) => {
2748
4120
  const mergedOptions = mergeOptions(options, selectOptions);
2749
4121
  const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
2750
4122
  const payload = {
@@ -2757,13 +4129,33 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
2757
4129
  if (state.pageSize !== void 0) payload.page_size = state.pageSize;
2758
4130
  if (state.totalPages !== void 0) payload.total_pages = state.totalPages;
2759
4131
  if (columns) payload.columns = columns;
2760
- const response = await client.deleteGateway(payload, mergedOptions);
2761
- return formatGatewayResult(response, { table: resolvedTableName, operation: "delete" });
4132
+ const sql = buildDeleteDebugSql(payload);
4133
+ return executeWithQueryTrace(
4134
+ tracer,
4135
+ {
4136
+ operation: "delete",
4137
+ endpoint: "/gateway/delete",
4138
+ table: resolvedTableName,
4139
+ sql,
4140
+ payload,
4141
+ options: mergedOptions
4142
+ },
4143
+ async () => {
4144
+ const response = await client.deleteGateway(payload, mergedOptions);
4145
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "delete" });
4146
+ },
4147
+ callsite
4148
+ );
2762
4149
  };
2763
- return createMutationQuery(executeDelete, null);
4150
+ return createMutationQuery(executeDelete, null, tracer, mutationCallsite);
2764
4151
  },
2765
4152
  async single(columns, options) {
2766
- const response = await builder.select(columns, options);
4153
+ const response = await runSelect(
4154
+ columns ?? DEFAULT_COLUMNS,
4155
+ options,
4156
+ snapshotState(),
4157
+ captureTraceCallsite(tracer)
4158
+ );
2767
4159
  return toSingleResult(response);
2768
4160
  },
2769
4161
  async maybeSingle(columns, options) {
@@ -2772,14 +4164,29 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
2772
4164
  });
2773
4165
  return builder;
2774
4166
  }
2775
- function createQueryBuilder(client, formatGatewayResult) {
4167
+ function createQueryBuilder(client, formatGatewayResult, tracer) {
2776
4168
  return async function query(query, options) {
2777
4169
  const normalizedQuery = query.trim();
2778
4170
  if (!normalizedQuery) {
2779
4171
  throw new Error("query requires a non-empty string");
2780
4172
  }
2781
- const response = await client.queryGateway({ query: normalizedQuery }, options);
2782
- return formatGatewayResult(response, { operation: "query" });
4173
+ const payload = { query: normalizedQuery };
4174
+ const callsite = captureTraceCallsite(tracer);
4175
+ return executeWithQueryTrace(
4176
+ tracer,
4177
+ {
4178
+ operation: "query",
4179
+ endpoint: "/gateway/query",
4180
+ sql: normalizedQuery,
4181
+ payload,
4182
+ options
4183
+ },
4184
+ async () => {
4185
+ const response = await client.queryGateway(payload, options);
4186
+ return formatGatewayResult(response, { operation: "query" });
4187
+ },
4188
+ callsite
4189
+ );
2783
4190
  };
2784
4191
  }
2785
4192
  function createClientFromConfig(config) {
@@ -2791,8 +4198,9 @@ function createClientFromConfig(config) {
2791
4198
  headers: config.headers
2792
4199
  });
2793
4200
  const formatGatewayResult = createResultFormatter(config.experimental);
4201
+ const queryTracer = createQueryTracer(config.experimental);
2794
4202
  const auth = createAuthClient(config.auth);
2795
- const from = (table) => createTableBuilder(table, gateway, formatGatewayResult);
4203
+ const from = (table) => createTableBuilder(table, gateway, formatGatewayResult, queryTracer, config.experimental);
2796
4204
  const rpc = (fn, args, options) => {
2797
4205
  const normalizedFn = fn.trim();
2798
4206
  if (!normalizedFn) {
@@ -2803,10 +4211,12 @@ function createClientFromConfig(config) {
2803
4211
  args,
2804
4212
  options,
2805
4213
  gateway,
2806
- formatGatewayResult
4214
+ formatGatewayResult,
4215
+ queryTracer,
4216
+ captureTraceCallsite(queryTracer)
2807
4217
  );
2808
4218
  };
2809
- const query = createQueryBuilder(gateway, formatGatewayResult);
4219
+ const query = createQueryBuilder(gateway, formatGatewayResult, queryTracer);
2810
4220
  const db = createDbModule({ from, rpc, query });
2811
4221
  return {
2812
4222
  from,
@@ -2821,12 +4231,40 @@ function toBackendConfig(b) {
2821
4231
  if (!b) return DEFAULT_BACKEND;
2822
4232
  return typeof b === "string" ? { type: b } : b;
2823
4233
  }
4234
+ function mergeAuthClientConfig(current, next) {
4235
+ const merged = {
4236
+ ...current ?? {},
4237
+ ...next
4238
+ };
4239
+ if (current?.headers || next.headers) {
4240
+ merged.headers = {
4241
+ ...current?.headers ?? {},
4242
+ ...next.headers ?? {}
4243
+ };
4244
+ }
4245
+ return merged;
4246
+ }
4247
+ function mergeExperimentalOptions(current, next) {
4248
+ const merged = {
4249
+ ...current ?? {},
4250
+ ...next
4251
+ };
4252
+ if (current?.traceQueries && typeof current.traceQueries === "object" && next.traceQueries && typeof next.traceQueries === "object") {
4253
+ merged.traceQueries = {
4254
+ ...current.traceQueries,
4255
+ ...next.traceQueries
4256
+ };
4257
+ }
4258
+ return merged;
4259
+ }
2824
4260
  var AthenaClientBuilderImpl = class {
2825
4261
  baseUrl;
2826
4262
  apiKey;
2827
4263
  backendConfig = DEFAULT_BACKEND;
2828
4264
  clientName;
2829
4265
  defaultHeaders;
4266
+ authConfig;
4267
+ experimentalOptions;
2830
4268
  isHealthTrackingEnabled = false;
2831
4269
  url(url) {
2832
4270
  this.baseUrl = url;
@@ -2848,6 +4286,35 @@ var AthenaClientBuilderImpl = class {
2848
4286
  this.defaultHeaders = headers;
2849
4287
  return this;
2850
4288
  }
4289
+ auth(config) {
4290
+ this.authConfig = mergeAuthClientConfig(this.authConfig, config);
4291
+ return this;
4292
+ }
4293
+ experimental(options) {
4294
+ this.experimentalOptions = mergeExperimentalOptions(this.experimentalOptions, options);
4295
+ return this;
4296
+ }
4297
+ options(options) {
4298
+ if (options.client !== void 0) {
4299
+ this.clientName = options.client;
4300
+ }
4301
+ if (options.backend !== void 0) {
4302
+ this.backendConfig = toBackendConfig(options.backend);
4303
+ }
4304
+ if (options.headers !== void 0) {
4305
+ this.defaultHeaders = {
4306
+ ...this.defaultHeaders ?? {},
4307
+ ...options.headers
4308
+ };
4309
+ }
4310
+ if (options.auth !== void 0) {
4311
+ this.authConfig = mergeAuthClientConfig(this.authConfig, options.auth);
4312
+ }
4313
+ if (options.experimental !== void 0) {
4314
+ this.experimentalOptions = mergeExperimentalOptions(this.experimentalOptions, options.experimental);
4315
+ }
4316
+ return this;
4317
+ }
2851
4318
  healthTracking(enabled) {
2852
4319
  this.isHealthTrackingEnabled = enabled;
2853
4320
  return this;
@@ -2862,7 +4329,9 @@ var AthenaClientBuilderImpl = class {
2862
4329
  client: this.clientName,
2863
4330
  backend: this.backendConfig,
2864
4331
  headers: this.defaultHeaders,
2865
- healthTracking: this.isHealthTrackingEnabled
4332
+ healthTracking: this.isHealthTrackingEnabled,
4333
+ auth: this.authConfig,
4334
+ experimental: this.experimentalOptions
2866
4335
  });
2867
4336
  }
2868
4337
  };
@@ -3042,7 +4511,7 @@ function resolveNullishValue(mode) {
3042
4511
  if (mode === "null") return null;
3043
4512
  return "";
3044
4513
  }
3045
- function isRecord4(value) {
4514
+ function isRecord7(value) {
3046
4515
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
3047
4516
  }
3048
4517
  function isNullableColumn(model, key) {
@@ -3051,7 +4520,7 @@ function isNullableColumn(model, key) {
3051
4520
  }
3052
4521
  function toModelFormDefaults(model, values, options) {
3053
4522
  const source = values;
3054
- if (!isRecord4(source)) {
4523
+ if (!isRecord7(source)) {
3055
4524
  return {};
3056
4525
  }
3057
4526
  const mode = options?.nullishMode ?? "empty-string";
@@ -3248,28 +4717,28 @@ function throwBrowserUnsupported(apiName) {
3248
4717
  `@xylex-group/athena: ${apiName} is not available in browser bundles. Use this API in a Node.js runtime.`
3249
4718
  );
3250
4719
  }
3251
- function createPostgresIntrospectionProvider(_options) {
4720
+ function createPostgresIntrospectionProvider(options) {
3252
4721
  return throwBrowserUnsupported("createPostgresIntrospectionProvider");
3253
4722
  }
3254
4723
  function defineGeneratorConfig(config) {
3255
4724
  return config;
3256
4725
  }
3257
- function findGeneratorConfigPath(_cwd) {
4726
+ function findGeneratorConfigPath(cwd) {
3258
4727
  return throwBrowserUnsupported("findGeneratorConfigPath");
3259
4728
  }
3260
- async function loadGeneratorConfig(_options = {}) {
4729
+ async function loadGeneratorConfig(options = {}) {
3261
4730
  return throwBrowserUnsupported("loadGeneratorConfig");
3262
4731
  }
3263
- function normalizeGeneratorConfig(_input) {
4732
+ function normalizeGeneratorConfig(input) {
3264
4733
  return throwBrowserUnsupported("normalizeGeneratorConfig");
3265
4734
  }
3266
- function generateArtifactsFromSnapshot(_snapshot, _config) {
4735
+ function generateArtifactsFromSnapshot(snapshot, config) {
3267
4736
  return throwBrowserUnsupported("generateArtifactsFromSnapshot");
3268
4737
  }
3269
- function resolveGeneratorProvider(_providerConfig, _experimentalFlags) {
4738
+ function resolveGeneratorProvider(providerConfig, experimentalFlags) {
3270
4739
  return throwBrowserUnsupported("resolveGeneratorProvider");
3271
4740
  }
3272
- async function runSchemaGenerator(_options = {}) {
4741
+ async function runSchemaGenerator(options = {}) {
3273
4742
  return throwBrowserUnsupported("runSchemaGenerator");
3274
4743
  }
3275
4744
 
@@ -3284,10 +4753,12 @@ exports.DEFAULT_POSTGRES_SCHEMAS = DEFAULT_POSTGRES_SCHEMAS;
3284
4753
  exports.assertInt = assertInt;
3285
4754
  exports.coerceInt = coerceInt;
3286
4755
  exports.createAuthClient = createAuthClient;
4756
+ exports.createAuthReactEmailInput = createAuthReactEmailInput;
3287
4757
  exports.createClient = createClient;
3288
4758
  exports.createModelFormAdapter = createModelFormAdapter;
3289
4759
  exports.createPostgresIntrospectionProvider = createPostgresIntrospectionProvider;
3290
4760
  exports.createTypedClient = createTypedClient;
4761
+ exports.defineAuthEmailTemplate = defineAuthEmailTemplate;
3291
4762
  exports.defineDatabase = defineDatabase;
3292
4763
  exports.defineGeneratorConfig = defineGeneratorConfig;
3293
4764
  exports.defineModel = defineModel;
@@ -3302,7 +4773,8 @@ exports.loadGeneratorConfig = loadGeneratorConfig;
3302
4773
  exports.normalizeAthenaError = normalizeAthenaError;
3303
4774
  exports.normalizeGeneratorConfig = normalizeGeneratorConfig;
3304
4775
  exports.normalizeSchemaSelection = normalizeSchemaSelection;
3305
- exports.parseBooleanFlag = parseBooleanFlag;
4776
+ exports.parseBooleanFlag = parseBooleanFlag2;
4777
+ exports.renderAthenaReactEmail = renderAthenaReactEmail;
3306
4778
  exports.requireAffected = requireAffected;
3307
4779
  exports.requireSuccess = requireSuccess;
3308
4780
  exports.resolveGeneratorProvider = resolveGeneratorProvider;