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