@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.
- package/README.md +287 -116
- package/dist/browser.cjs +1628 -156
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +14 -14
- package/dist/browser.d.ts +14 -14
- package/dist/browser.js +1625 -156
- package/dist/browser.js.map +1 -1
- package/dist/cli/index.cjs +1532 -145
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts +3 -3
- package/dist/cli/index.d.ts +3 -3
- package/dist/cli/index.js +1533 -146
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +1658 -167
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +1656 -168
- package/dist/index.js.map +1 -1
- package/dist/{model-form-2hqmoOUX.d.ts → model-form-BpDXlbxb.d.ts} +97 -2
- package/dist/{model-form-Cy-zaO0u.d.cts → model-form-hoE2jHIi.d.cts} +97 -2
- package/dist/{pipeline-BOPszLsL.d.ts → pipeline-BNIw8pDQ.d.ts} +1 -1
- package/dist/{pipeline-E3FDbs4W.d.cts → pipeline-DNIpEsN8.d.cts} +1 -1
- package/dist/{client-dpAp-NZK.d.cts → react-email-BvyCZnfW.d.cts} +349 -174
- package/dist/{client-BX0NQqOn.d.ts → react-email-qPA1wjFV.d.ts} +349 -174
- package/dist/react.cjs +30 -9
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +4 -4
- package/dist/react.d.ts +4 -4
- package/dist/react.js +30 -9
- package/dist/react.js.map +1 -1
- package/dist/{types-BaBzjwXr.d.cts → types-A5e97acl.d.cts} +2 -1
- package/dist/{types-BaBzjwXr.d.ts → types-A5e97acl.d.ts} +2 -1
- package/dist/{types-CeBPrnGj.d.ts → types-BnD22-vb.d.ts} +1 -1
- package/dist/{types-CpqL-pZx.d.cts → types-bDlr4u7p.d.cts} +1 -1
- package/dist/utils.cjs +153 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.d.cts +23 -0
- package/dist/utils.d.ts +23 -0
- package/dist/utils.js +146 -0
- package/dist/utils.js.map +1 -0
- 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
|
-
|
|
96
|
-
|
|
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
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
106
|
+
const resolved = nonEmptyString(candidate);
|
|
107
|
+
if (resolved) return resolved;
|
|
101
108
|
}
|
|
102
109
|
}
|
|
103
|
-
|
|
104
|
-
|
|
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
|
|
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
|
|
385
|
-
if (!
|
|
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
|
-
|
|
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
|
|
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 (
|
|
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 =
|
|
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(
|
|
1324
|
-
|
|
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(
|
|
1337
|
-
|
|
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(
|
|
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(
|
|
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
|
|
1568
|
-
|
|
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
|
|
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
|
|
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 (!
|
|
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
|
|
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:
|
|
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
|
|
1778
|
-
const
|
|
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 =
|
|
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:
|
|
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 (
|
|
2704
|
+
if (response.error == null && response.errorDetails == null) {
|
|
2065
2705
|
return result;
|
|
2066
2706
|
}
|
|
2067
|
-
const normalizedError = normalizeAthenaError(
|
|
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
|
|
2073
|
-
|
|
2074
|
-
|
|
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
|
|
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
|
|
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) =>
|
|
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
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
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 "${
|
|
3110
|
+
`schema option "${normalizedSchema}" conflicts with schema-qualified table "${normalizedTableName}"`
|
|
2192
3111
|
);
|
|
2193
3112
|
}
|
|
2194
|
-
return `${normalizedSchema}.${
|
|
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}.${
|
|
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
|
|
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
|
|
2468
|
-
|
|
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 =
|
|
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:
|
|
2572
|
-
offset:
|
|
2573
|
-
currentPage:
|
|
2574
|
-
pageSize:
|
|
2575
|
-
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
|
|
2579
|
-
return
|
|
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:
|
|
2587
|
-
offset:
|
|
2588
|
-
current_page:
|
|
2589
|
-
page_size:
|
|
2590
|
-
total_pages:
|
|
2591
|
-
sort_by:
|
|
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
|
|
2597
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
3840
|
+
return runSelect(columns, options, snapshotState(), callsiteStore.resolve()).catch(
|
|
3841
|
+
onrejected
|
|
3842
|
+
);
|
|
2615
3843
|
},
|
|
2616
3844
|
finally(onfinally) {
|
|
2617
|
-
return runSelect(columns, options).finally(
|
|
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
|
|
2652
|
-
return
|
|
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
|
|
2670
|
-
return
|
|
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
|
|
2692
|
-
return
|
|
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
|
|
2712
|
-
return
|
|
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
|
|
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
|
|
2733
|
-
return
|
|
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
|
|
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
|
|
2761
|
-
return
|
|
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
|
|
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
|
|
2782
|
-
|
|
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
|
|
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 (!
|
|
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(
|
|
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(
|
|
4726
|
+
function findGeneratorConfigPath(cwd) {
|
|
3258
4727
|
return throwBrowserUnsupported("findGeneratorConfigPath");
|
|
3259
4728
|
}
|
|
3260
|
-
async function loadGeneratorConfig(
|
|
4729
|
+
async function loadGeneratorConfig(options = {}) {
|
|
3261
4730
|
return throwBrowserUnsupported("loadGeneratorConfig");
|
|
3262
4731
|
}
|
|
3263
|
-
function normalizeGeneratorConfig(
|
|
4732
|
+
function normalizeGeneratorConfig(input) {
|
|
3264
4733
|
return throwBrowserUnsupported("normalizeGeneratorConfig");
|
|
3265
4734
|
}
|
|
3266
|
-
function generateArtifactsFromSnapshot(
|
|
4735
|
+
function generateArtifactsFromSnapshot(snapshot, config) {
|
|
3267
4736
|
return throwBrowserUnsupported("generateArtifactsFromSnapshot");
|
|
3268
4737
|
}
|
|
3269
|
-
function resolveGeneratorProvider(
|
|
4738
|
+
function resolveGeneratorProvider(providerConfig, experimentalFlags) {
|
|
3270
4739
|
return throwBrowserUnsupported("resolveGeneratorProvider");
|
|
3271
4740
|
}
|
|
3272
|
-
async function runSchemaGenerator(
|
|
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 =
|
|
4776
|
+
exports.parseBooleanFlag = parseBooleanFlag2;
|
|
4777
|
+
exports.renderAthenaReactEmail = renderAthenaReactEmail;
|
|
3306
4778
|
exports.requireAffected = requireAffected;
|
|
3307
4779
|
exports.requireSuccess = requireSuccess;
|
|
3308
4780
|
exports.resolveGeneratorProvider = resolveGeneratorProvider;
|