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