@xylex-group/athena 2.1.2 → 2.4.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 +306 -117
- package/dist/browser.cjs +2151 -194
- 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 +2146 -194
- package/dist/browser.js.map +1 -1
- package/dist/cli/index.cjs +2035 -172
- 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 +2036 -173
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +2166 -190
- 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 +2162 -191
- package/dist/index.js.map +1 -1
- package/dist/{model-form-2hqmoOUX.d.ts → model-form-C0FAbOaf.d.ts} +97 -2
- package/dist/{model-form-Cy-zaO0u.d.cts → model-form-GzTqhEzM.d.cts} +97 -2
- package/dist/{pipeline-BOPszLsL.d.ts → pipeline-CR4V15jF.d.ts} +1 -1
- package/dist/{pipeline-E3FDbs4W.d.cts → pipeline-DZeExYMA.d.cts} +1 -1
- package/dist/{client-BX0NQqOn.d.ts → react-email-BuApZuyG.d.ts} +362 -174
- package/dist/{client-dpAp-NZK.d.cts → react-email-CQJq92zQ.d.cts} +362 -174
- package/dist/react.cjs +279 -21
- 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 +279 -21
- package/dist/react.js.map +1 -1
- package/dist/{types-BaBzjwXr.d.cts → types-09Q4D86N.d.cts} +24 -2
- package/dist/{types-BaBzjwXr.d.ts → types-09Q4D86N.d.ts} +24 -2
- package/dist/{types-CpqL-pZx.d.cts → types-D1JvL21V.d.cts} +1 -1
- package/dist/{types-CeBPrnGj.d.ts → types-DU3gNdFv.d.ts} +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 +74 -16
package/dist/browser.cjs
CHANGED
|
@@ -60,8 +60,74 @@ function isAthenaGatewayError(error) {
|
|
|
60
60
|
return error instanceof AthenaGatewayError;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
// src/gateway/url.ts
|
|
64
|
+
var ATHENA_DEFAULT_BASE_URL = "https://athena-db.com";
|
|
65
|
+
function describeReceivedValue(value) {
|
|
66
|
+
if (value === void 0) return "undefined";
|
|
67
|
+
if (value === null) return "null";
|
|
68
|
+
if (typeof value === "string") {
|
|
69
|
+
return value.trim().length > 0 ? JSON.stringify(value) : "an empty string";
|
|
70
|
+
}
|
|
71
|
+
return `${typeof value} ${JSON.stringify(value)}`;
|
|
72
|
+
}
|
|
73
|
+
function invalidBaseUrlError(message, hint) {
|
|
74
|
+
return new AthenaGatewayError({
|
|
75
|
+
code: "INVALID_URL",
|
|
76
|
+
message,
|
|
77
|
+
status: 0,
|
|
78
|
+
hint
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
function normalizeAthenaGatewayBaseUrl(input, options = {}) {
|
|
82
|
+
const label = options.label ?? "Athena gateway base URL";
|
|
83
|
+
const candidate = input ?? options.defaultBaseUrl;
|
|
84
|
+
if (candidate === void 0 || candidate === null) {
|
|
85
|
+
throw invalidBaseUrlError(
|
|
86
|
+
`${label} must be a non-empty absolute http(s) URL. Received ${describeReceivedValue(input)}.`,
|
|
87
|
+
'Set ATHENA_URL (or pass createClient(url, ...)) to a full URL such as "https://mirror3.athena-db.com".'
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
const trimmed = candidate.trim();
|
|
91
|
+
if (!trimmed) {
|
|
92
|
+
throw invalidBaseUrlError(
|
|
93
|
+
`${label} must be a non-empty absolute http(s) URL. Received ${describeReceivedValue(candidate)}.`,
|
|
94
|
+
'Set ATHENA_URL (or pass createClient(url, ...)) to a full URL such as "https://mirror3.athena-db.com".'
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
let parsed;
|
|
98
|
+
try {
|
|
99
|
+
parsed = new URL(trimmed);
|
|
100
|
+
} catch {
|
|
101
|
+
throw invalidBaseUrlError(
|
|
102
|
+
`${label} must be a valid absolute http(s) URL. Received ${describeReceivedValue(candidate)}.`,
|
|
103
|
+
'Use a full URL including the protocol, for example "https://mirror3.athena-db.com".'
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
107
|
+
throw invalidBaseUrlError(
|
|
108
|
+
`${label} must use http or https. Received ${JSON.stringify(trimmed)}.`,
|
|
109
|
+
'Use an Athena gateway URL such as "https://mirror3.athena-db.com".'
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
if (parsed.search || parsed.hash) {
|
|
113
|
+
throw invalidBaseUrlError(
|
|
114
|
+
`${label} must not include query parameters or hash fragments. Received ${JSON.stringify(trimmed)}.`,
|
|
115
|
+
'Pass only the base URL. Endpoint paths such as "/gateway/fetch" are appended by the SDK.'
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
return parsed.toString().replace(/\/+$/, "");
|
|
119
|
+
}
|
|
120
|
+
function buildAthenaGatewayUrl(baseUrl, path) {
|
|
121
|
+
if (!path.startsWith("/")) {
|
|
122
|
+
throw invalidBaseUrlError(
|
|
123
|
+
`Athena gateway path must start with "/". Received ${JSON.stringify(path)}.`,
|
|
124
|
+
'Use a leading slash such as "/gateway/fetch" or "/".'
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
return `${baseUrl}${path}`;
|
|
128
|
+
}
|
|
129
|
+
|
|
63
130
|
// src/gateway/client.ts
|
|
64
|
-
var DEFAULT_BASE_URL = "https://athena-db.com";
|
|
65
131
|
var DEFAULT_CLIENT = "railway_direct";
|
|
66
132
|
var FALLBACK_SDK_VERSION = "1.3.0";
|
|
67
133
|
var SDK_NAME = "xylex-group/athena";
|
|
@@ -88,23 +154,39 @@ function normalizeHeaderValue(value) {
|
|
|
88
154
|
function isRecord(value) {
|
|
89
155
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
90
156
|
}
|
|
157
|
+
function nonEmptyString(value) {
|
|
158
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
159
|
+
}
|
|
160
|
+
function resolveStructuredErrorPayload(payload) {
|
|
161
|
+
if (!isRecord(payload)) return null;
|
|
162
|
+
return isRecord(payload.error) ? payload.error : payload;
|
|
163
|
+
}
|
|
91
164
|
function resolveRequestId(headers) {
|
|
92
165
|
return headers.get("x-request-id") ?? headers.get("x-correlation-id") ?? headers.get("x-athena-request-id") ?? void 0;
|
|
93
166
|
}
|
|
94
167
|
function resolveErrorMessage(payload, fallback) {
|
|
95
|
-
|
|
96
|
-
|
|
168
|
+
const structuredPayload = resolveStructuredErrorPayload(payload);
|
|
169
|
+
if (structuredPayload) {
|
|
170
|
+
const messageCandidates = [structuredPayload.message, structuredPayload.error, structuredPayload.details];
|
|
97
171
|
for (const candidate of messageCandidates) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
172
|
+
const resolved = nonEmptyString(candidate);
|
|
173
|
+
if (resolved) return resolved;
|
|
101
174
|
}
|
|
102
175
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
176
|
+
const rawMessage = nonEmptyString(payload);
|
|
177
|
+
if (rawMessage) return rawMessage;
|
|
106
178
|
return fallback;
|
|
107
179
|
}
|
|
180
|
+
function resolveErrorHint(payload) {
|
|
181
|
+
const structuredPayload = resolveStructuredErrorPayload(payload);
|
|
182
|
+
return structuredPayload ? nonEmptyString(structuredPayload.hint) : void 0;
|
|
183
|
+
}
|
|
184
|
+
function resolveStatusText(response, payload) {
|
|
185
|
+
const rawStatusText = nonEmptyString(response.statusText);
|
|
186
|
+
if (rawStatusText) return rawStatusText;
|
|
187
|
+
const payloadRecord = isRecord(payload) ? payload : null;
|
|
188
|
+
return payloadRecord ? nonEmptyString(payloadRecord.statusText) ?? null : null;
|
|
189
|
+
}
|
|
108
190
|
function detailsFromError(error) {
|
|
109
191
|
return error.toDetails();
|
|
110
192
|
}
|
|
@@ -242,9 +324,172 @@ function buildHeaders(config, options) {
|
|
|
242
324
|
});
|
|
243
325
|
return headers;
|
|
244
326
|
}
|
|
327
|
+
function toInvalidUrlResponse(error, endpoint, method) {
|
|
328
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
329
|
+
const gatewayError = error instanceof AthenaGatewayError ? error : new AthenaGatewayError({
|
|
330
|
+
code: "INVALID_URL",
|
|
331
|
+
message,
|
|
332
|
+
status: 0,
|
|
333
|
+
endpoint,
|
|
334
|
+
method,
|
|
335
|
+
cause: message,
|
|
336
|
+
hint: "Set ATHENA_URL to a full http(s) URL before running queries."
|
|
337
|
+
});
|
|
338
|
+
return {
|
|
339
|
+
ok: false,
|
|
340
|
+
status: 0,
|
|
341
|
+
statusText: null,
|
|
342
|
+
data: null,
|
|
343
|
+
error: gatewayError.message,
|
|
344
|
+
errorDetails: detailsFromError(
|
|
345
|
+
new AthenaGatewayError({
|
|
346
|
+
code: gatewayError.code,
|
|
347
|
+
message: gatewayError.message,
|
|
348
|
+
status: gatewayError.status,
|
|
349
|
+
endpoint,
|
|
350
|
+
method,
|
|
351
|
+
requestId: gatewayError.requestId,
|
|
352
|
+
hint: gatewayError.hint,
|
|
353
|
+
cause: gatewayError.causeDetail
|
|
354
|
+
})
|
|
355
|
+
),
|
|
356
|
+
raw: null
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
function resolveGatewayBaseUrl(input) {
|
|
360
|
+
return normalizeAthenaGatewayBaseUrl(input, {
|
|
361
|
+
defaultBaseUrl: ATHENA_DEFAULT_BASE_URL
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
function resolveProbePath(path) {
|
|
365
|
+
if (!path) return "/";
|
|
366
|
+
if (!path.startsWith("/")) {
|
|
367
|
+
throw new AthenaGatewayError({
|
|
368
|
+
code: "INVALID_URL",
|
|
369
|
+
message: `Athena gateway probe path must start with "/". Received ${JSON.stringify(path)}.`,
|
|
370
|
+
status: 0,
|
|
371
|
+
hint: 'Use a leading slash such as "/" or "/health".'
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
return path;
|
|
375
|
+
}
|
|
376
|
+
function mergeConnectionHeaders(baseHeaders, headers) {
|
|
377
|
+
const merged = {
|
|
378
|
+
...baseHeaders,
|
|
379
|
+
...headers ?? {}
|
|
380
|
+
};
|
|
381
|
+
if (!merged["X-Athena-Sdk"] && !merged["x-athena-sdk"]) {
|
|
382
|
+
merged["X-Athena-Sdk"] = SDK_HEADER_VALUE;
|
|
383
|
+
}
|
|
384
|
+
return merged;
|
|
385
|
+
}
|
|
386
|
+
async function performConnectionCheck(baseUrl, requestHeaders, options) {
|
|
387
|
+
const path = resolveProbePath(options?.path);
|
|
388
|
+
const url = buildAthenaGatewayUrl(baseUrl, path);
|
|
389
|
+
try {
|
|
390
|
+
const response = await fetch(url, {
|
|
391
|
+
method: "GET",
|
|
392
|
+
headers: mergeConnectionHeaders(requestHeaders, options?.headers),
|
|
393
|
+
signal: options?.signal
|
|
394
|
+
});
|
|
395
|
+
const rawText = await response.text();
|
|
396
|
+
const requestId = resolveRequestId(response.headers);
|
|
397
|
+
const parsedBody = parseResponseBody(
|
|
398
|
+
rawText ?? "",
|
|
399
|
+
response.headers.get("content-type")
|
|
400
|
+
);
|
|
401
|
+
if (parsedBody.parseFailed) {
|
|
402
|
+
const invalidJsonError = new AthenaGatewayError({
|
|
403
|
+
code: "INVALID_JSON",
|
|
404
|
+
message: "Gateway probe returned malformed JSON",
|
|
405
|
+
status: response.status,
|
|
406
|
+
method: "GET",
|
|
407
|
+
requestId,
|
|
408
|
+
hint: "Verify the gateway response body is valid JSON.",
|
|
409
|
+
cause: rawText.slice(0, 300)
|
|
410
|
+
});
|
|
411
|
+
return {
|
|
412
|
+
ok: false,
|
|
413
|
+
reachable: true,
|
|
414
|
+
status: response.status,
|
|
415
|
+
statusText: resolveStatusText(response, parsedBody.parsed),
|
|
416
|
+
baseUrl,
|
|
417
|
+
url,
|
|
418
|
+
error: invalidJsonError.message,
|
|
419
|
+
errorDetails: detailsFromError(invalidJsonError),
|
|
420
|
+
raw: parsedBody.parsed
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
const parsed = parsedBody.parsed;
|
|
424
|
+
if (!response.ok) {
|
|
425
|
+
const httpError = new AthenaGatewayError({
|
|
426
|
+
code: "HTTP_ERROR",
|
|
427
|
+
message: resolveErrorMessage(
|
|
428
|
+
parsed,
|
|
429
|
+
`Athena gateway GET ${path} failed with status ${response.status}`
|
|
430
|
+
),
|
|
431
|
+
status: response.status,
|
|
432
|
+
method: "GET",
|
|
433
|
+
requestId,
|
|
434
|
+
hint: resolveErrorHint(parsed)
|
|
435
|
+
});
|
|
436
|
+
return {
|
|
437
|
+
ok: false,
|
|
438
|
+
reachable: true,
|
|
439
|
+
status: response.status,
|
|
440
|
+
statusText: resolveStatusText(response, parsed),
|
|
441
|
+
baseUrl,
|
|
442
|
+
url,
|
|
443
|
+
error: httpError.message,
|
|
444
|
+
errorDetails: detailsFromError(httpError),
|
|
445
|
+
raw: parsed
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
return {
|
|
449
|
+
ok: true,
|
|
450
|
+
reachable: true,
|
|
451
|
+
status: response.status,
|
|
452
|
+
statusText: resolveStatusText(response, parsed),
|
|
453
|
+
baseUrl,
|
|
454
|
+
url,
|
|
455
|
+
error: void 0,
|
|
456
|
+
errorDetails: null,
|
|
457
|
+
raw: parsed
|
|
458
|
+
};
|
|
459
|
+
} catch (callError) {
|
|
460
|
+
const message = callError instanceof Error ? callError.message : String(callError);
|
|
461
|
+
const networkError = new AthenaGatewayError({
|
|
462
|
+
code: "NETWORK_ERROR",
|
|
463
|
+
message: `Network error while probing Athena gateway ${url}: ${message}`,
|
|
464
|
+
method: "GET",
|
|
465
|
+
cause: message,
|
|
466
|
+
hint: "Check gateway URL, DNS, and network reachability."
|
|
467
|
+
});
|
|
468
|
+
return {
|
|
469
|
+
ok: false,
|
|
470
|
+
reachable: false,
|
|
471
|
+
status: 0,
|
|
472
|
+
statusText: null,
|
|
473
|
+
baseUrl,
|
|
474
|
+
url,
|
|
475
|
+
error: networkError.message,
|
|
476
|
+
errorDetails: detailsFromError(networkError),
|
|
477
|
+
raw: null
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
async function verifyAthenaGatewayUrl(baseUrl, options) {
|
|
482
|
+
const normalizedBaseUrl = normalizeAthenaGatewayBaseUrl(baseUrl);
|
|
483
|
+
return performConnectionCheck(normalizedBaseUrl, { "X-Athena-Sdk": SDK_HEADER_VALUE }, options);
|
|
484
|
+
}
|
|
245
485
|
async function callAthena(config, endpoint, method, payload, options) {
|
|
246
|
-
|
|
247
|
-
|
|
486
|
+
let baseUrl;
|
|
487
|
+
try {
|
|
488
|
+
baseUrl = resolveGatewayBaseUrl(options?.baseUrl ?? config.baseUrl);
|
|
489
|
+
} catch (error) {
|
|
490
|
+
return toInvalidUrlResponse(error, endpoint, method);
|
|
491
|
+
}
|
|
492
|
+
const url = buildAthenaGatewayUrl(baseUrl, endpoint);
|
|
248
493
|
const headers = buildHeaders(config, options);
|
|
249
494
|
try {
|
|
250
495
|
const requestInit = {
|
|
@@ -275,6 +520,7 @@ async function callAthena(config, endpoint, method, payload, options) {
|
|
|
275
520
|
return {
|
|
276
521
|
ok: false,
|
|
277
522
|
status: response.status,
|
|
523
|
+
statusText: resolveStatusText(response, parsedBody.parsed),
|
|
278
524
|
data: null,
|
|
279
525
|
error: invalidJsonError.message,
|
|
280
526
|
errorDetails: detailsFromError(invalidJsonError),
|
|
@@ -293,11 +539,13 @@ async function callAthena(config, endpoint, method, payload, options) {
|
|
|
293
539
|
status: response.status,
|
|
294
540
|
endpoint,
|
|
295
541
|
method,
|
|
296
|
-
requestId
|
|
542
|
+
requestId,
|
|
543
|
+
hint: resolveErrorHint(parsed)
|
|
297
544
|
});
|
|
298
545
|
return {
|
|
299
546
|
ok: false,
|
|
300
547
|
status: response.status,
|
|
548
|
+
statusText: resolveStatusText(response, parsed),
|
|
301
549
|
data: null,
|
|
302
550
|
error: httpError.message,
|
|
303
551
|
errorDetails: detailsFromError(httpError),
|
|
@@ -309,6 +557,7 @@ async function callAthena(config, endpoint, method, payload, options) {
|
|
|
309
557
|
return {
|
|
310
558
|
ok: true,
|
|
311
559
|
status: response.status,
|
|
560
|
+
statusText: resolveStatusText(response, parsed),
|
|
312
561
|
data: payloadData ?? null,
|
|
313
562
|
count: payloadCount,
|
|
314
563
|
error: void 0,
|
|
@@ -328,6 +577,7 @@ async function callAthena(config, endpoint, method, payload, options) {
|
|
|
328
577
|
return {
|
|
329
578
|
ok: false,
|
|
330
579
|
status: 0,
|
|
580
|
+
statusText: null,
|
|
331
581
|
data: null,
|
|
332
582
|
error: networkError.message,
|
|
333
583
|
errorDetails: detailsFromError(networkError),
|
|
@@ -336,32 +586,44 @@ async function callAthena(config, endpoint, method, payload, options) {
|
|
|
336
586
|
}
|
|
337
587
|
}
|
|
338
588
|
function createAthenaGatewayClient(config = {}) {
|
|
589
|
+
const normalizedBaseUrl = resolveGatewayBaseUrl(config.baseUrl);
|
|
590
|
+
const normalizedConfig = {
|
|
591
|
+
...config,
|
|
592
|
+
baseUrl: normalizedBaseUrl
|
|
593
|
+
};
|
|
339
594
|
return {
|
|
340
|
-
baseUrl:
|
|
595
|
+
baseUrl: normalizedBaseUrl,
|
|
341
596
|
buildHeaders(options) {
|
|
342
|
-
return buildHeaders(
|
|
597
|
+
return buildHeaders(normalizedConfig, options);
|
|
598
|
+
},
|
|
599
|
+
verifyConnection(options) {
|
|
600
|
+
return performConnectionCheck(
|
|
601
|
+
normalizedBaseUrl,
|
|
602
|
+
buildHeaders(normalizedConfig),
|
|
603
|
+
options
|
|
604
|
+
);
|
|
343
605
|
},
|
|
344
606
|
fetchGateway(payload, options) {
|
|
345
|
-
return callAthena(
|
|
607
|
+
return callAthena(normalizedConfig, "/gateway/fetch", "POST", payload, options);
|
|
346
608
|
},
|
|
347
609
|
insertGateway(payload, options) {
|
|
348
|
-
return callAthena(
|
|
610
|
+
return callAthena(normalizedConfig, "/gateway/insert", "PUT", payload, options);
|
|
349
611
|
},
|
|
350
612
|
updateGateway(payload, options) {
|
|
351
|
-
return callAthena(
|
|
613
|
+
return callAthena(normalizedConfig, "/gateway/update", "POST", payload, options);
|
|
352
614
|
},
|
|
353
615
|
deleteGateway(payload, options) {
|
|
354
|
-
return callAthena(
|
|
616
|
+
return callAthena(normalizedConfig, "/gateway/delete", "DELETE", payload, options);
|
|
355
617
|
},
|
|
356
618
|
rpcGateway(payload, options) {
|
|
357
619
|
if (options?.get) {
|
|
358
620
|
const endpoint = buildRpcGetEndpoint(payload);
|
|
359
|
-
return callAthena(
|
|
621
|
+
return callAthena(normalizedConfig, endpoint, "GET", null, options);
|
|
360
622
|
}
|
|
361
|
-
return callAthena(
|
|
623
|
+
return callAthena(normalizedConfig, "/gateway/rpc", "POST", payload, options);
|
|
362
624
|
},
|
|
363
625
|
queryGateway(payload, options) {
|
|
364
|
-
return callAthena(
|
|
626
|
+
return callAthena(normalizedConfig, "/gateway/query", "POST", payload, options);
|
|
365
627
|
}
|
|
366
628
|
};
|
|
367
629
|
}
|
|
@@ -369,10 +631,29 @@ function createAthenaGatewayClient(config = {}) {
|
|
|
369
631
|
// src/sql-identifiers.ts
|
|
370
632
|
var SIMPLE_IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
371
633
|
var COMPOSITE_IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/;
|
|
372
|
-
var
|
|
634
|
+
var SQL_ALIAS_PATTERN = /^([A-Za-z_][A-Za-z0-9_.]*)\s+(?:as\s+)?([A-Za-z_][A-Za-z0-9_]*)$/i;
|
|
635
|
+
var RESPONSE_ALIAS_PATTERN = /^([A-Za-z_][A-Za-z0-9_]*)\s*:\s*([A-Za-z_][A-Za-z0-9_.]*)$/i;
|
|
373
636
|
function quoteIdentifierSegment(identifier2) {
|
|
374
637
|
return `"${identifier2.replace(/"/g, '""')}"`;
|
|
375
638
|
}
|
|
639
|
+
function parseAliasedIdentifierToken(token) {
|
|
640
|
+
const responseAliasMatch = RESPONSE_ALIAS_PATTERN.exec(token);
|
|
641
|
+
if (responseAliasMatch) {
|
|
642
|
+
const [, aliasIdentifier2, baseIdentifier2] = responseAliasMatch;
|
|
643
|
+
if (COMPOSITE_IDENTIFIER_PATTERN.test(baseIdentifier2) && SIMPLE_IDENTIFIER_PATTERN.test(aliasIdentifier2)) {
|
|
644
|
+
return { baseIdentifier: baseIdentifier2, aliasIdentifier: aliasIdentifier2 };
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
const sqlAliasMatch = SQL_ALIAS_PATTERN.exec(token);
|
|
648
|
+
if (!sqlAliasMatch) {
|
|
649
|
+
return null;
|
|
650
|
+
}
|
|
651
|
+
const [, baseIdentifier, aliasIdentifier] = sqlAliasMatch;
|
|
652
|
+
if (!COMPOSITE_IDENTIFIER_PATTERN.test(baseIdentifier) || !SIMPLE_IDENTIFIER_PATTERN.test(aliasIdentifier)) {
|
|
653
|
+
return null;
|
|
654
|
+
}
|
|
655
|
+
return { baseIdentifier, aliasIdentifier };
|
|
656
|
+
}
|
|
376
657
|
function quoteQualifiedIdentifier(identifier2) {
|
|
377
658
|
return identifier2.split(".").map((segment) => quoteIdentifierSegment(segment)).join(".");
|
|
378
659
|
}
|
|
@@ -381,23 +662,27 @@ function quoteSelectToken(token) {
|
|
|
381
662
|
if (COMPOSITE_IDENTIFIER_PATTERN.test(token)) {
|
|
382
663
|
return quoteQualifiedIdentifier(token);
|
|
383
664
|
}
|
|
384
|
-
const
|
|
385
|
-
if (!
|
|
386
|
-
return token;
|
|
387
|
-
}
|
|
388
|
-
const [, baseIdentifier, aliasIdentifier] = aliasMatch;
|
|
389
|
-
if (!COMPOSITE_IDENTIFIER_PATTERN.test(baseIdentifier) || !SIMPLE_IDENTIFIER_PATTERN.test(aliasIdentifier)) {
|
|
665
|
+
const aliasedIdentifier = parseAliasedIdentifierToken(token);
|
|
666
|
+
if (!aliasedIdentifier) {
|
|
390
667
|
return token;
|
|
391
668
|
}
|
|
669
|
+
const { baseIdentifier, aliasIdentifier } = aliasedIdentifier;
|
|
392
670
|
return `${quoteQualifiedIdentifier(baseIdentifier)} AS ${quoteIdentifierSegment(aliasIdentifier)}`;
|
|
393
671
|
}
|
|
672
|
+
function quoteSelectColumnToken(token) {
|
|
673
|
+
const trimmed = token.trim();
|
|
674
|
+
if (!trimmed || trimmed === "*") return trimmed || "*";
|
|
675
|
+
const responseAliasMatch = RESPONSE_ALIAS_PATTERN.exec(trimmed);
|
|
676
|
+
if (responseAliasMatch) {
|
|
677
|
+
const [, aliasIdentifier, baseIdentifier] = responseAliasMatch;
|
|
678
|
+
return `${quoteQualifiedIdentifier(baseIdentifier)} AS ${quoteIdentifierSegment(aliasIdentifier)}`;
|
|
679
|
+
}
|
|
680
|
+
return quoteQualifiedIdentifier(trimmed);
|
|
681
|
+
}
|
|
394
682
|
function canAutoQuoteToken(token) {
|
|
395
683
|
if (token === "*") return true;
|
|
396
684
|
if (COMPOSITE_IDENTIFIER_PATTERN.test(token)) return true;
|
|
397
|
-
|
|
398
|
-
if (!aliasMatch) return false;
|
|
399
|
-
const [, baseIdentifier, aliasIdentifier] = aliasMatch;
|
|
400
|
-
return COMPOSITE_IDENTIFIER_PATTERN.test(baseIdentifier) && SIMPLE_IDENTIFIER_PATTERN.test(aliasIdentifier);
|
|
685
|
+
return parseAliasedIdentifierToken(token) != null;
|
|
401
686
|
}
|
|
402
687
|
function splitTopLevelCommaSeparated(input) {
|
|
403
688
|
const parts = [];
|
|
@@ -497,6 +782,231 @@ function identifier(...segments) {
|
|
|
497
782
|
return new SqlIdentifierPath(expandedSegments);
|
|
498
783
|
}
|
|
499
784
|
|
|
785
|
+
// src/auth/react-email.ts
|
|
786
|
+
var reactEmailRenderModulePromise;
|
|
787
|
+
function isRecord2(value) {
|
|
788
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
789
|
+
}
|
|
790
|
+
function isFunction(value) {
|
|
791
|
+
return typeof value === "function";
|
|
792
|
+
}
|
|
793
|
+
function toStringOrUndefined(value) {
|
|
794
|
+
if (typeof value !== "string") return void 0;
|
|
795
|
+
return value;
|
|
796
|
+
}
|
|
797
|
+
function nowIsoString() {
|
|
798
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
799
|
+
}
|
|
800
|
+
function emitReactEmailEvent(observe, phase, input = {}) {
|
|
801
|
+
if (!observe) return;
|
|
802
|
+
try {
|
|
803
|
+
observe({
|
|
804
|
+
phase,
|
|
805
|
+
timestamp: nowIsoString(),
|
|
806
|
+
...input
|
|
807
|
+
});
|
|
808
|
+
} catch {
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
function mergeRenderDefaults(input, defaults) {
|
|
812
|
+
return {
|
|
813
|
+
...input,
|
|
814
|
+
pretty: input.pretty ?? defaults?.pretty,
|
|
815
|
+
includePlainText: input.includePlainText ?? defaults?.includePlainText
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
function mergeRuntimeOptions(options) {
|
|
819
|
+
if (!options) return void 0;
|
|
820
|
+
return {
|
|
821
|
+
defaults: options.defaults,
|
|
822
|
+
observe: options.observe,
|
|
823
|
+
route: "route" in options ? options.route : void 0
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
async function resolveReactEmailRenderModule() {
|
|
827
|
+
if (!reactEmailRenderModulePromise) {
|
|
828
|
+
reactEmailRenderModulePromise = (async () => {
|
|
829
|
+
try {
|
|
830
|
+
const loaded = await import('@react-email/render');
|
|
831
|
+
if (!isFunction(loaded.render)) {
|
|
832
|
+
throw new Error("missing render(...) export");
|
|
833
|
+
}
|
|
834
|
+
return {
|
|
835
|
+
render: loaded.render,
|
|
836
|
+
toPlainText: isFunction(loaded.toPlainText) ? loaded.toPlainText : void 0,
|
|
837
|
+
pretty: isFunction(loaded.pretty) ? loaded.pretty : void 0
|
|
838
|
+
};
|
|
839
|
+
} catch (error) {
|
|
840
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
841
|
+
throw new Error(
|
|
842
|
+
`React Email rendering requires @react-email/render. Install it in your project (for example: pnpm add @react-email/render). Loader error: ${message}`
|
|
843
|
+
);
|
|
844
|
+
}
|
|
845
|
+
})();
|
|
846
|
+
}
|
|
847
|
+
if (!reactEmailRenderModulePromise) {
|
|
848
|
+
throw new Error("React Email renderer module failed to initialize");
|
|
849
|
+
}
|
|
850
|
+
return reactEmailRenderModulePromise;
|
|
851
|
+
}
|
|
852
|
+
async function resolveReactEmailElement(input) {
|
|
853
|
+
if (input.element != null) {
|
|
854
|
+
return input.element;
|
|
855
|
+
}
|
|
856
|
+
if (!input.component) {
|
|
857
|
+
throw new Error("react email payload requires either `element` or `component`");
|
|
858
|
+
}
|
|
859
|
+
try {
|
|
860
|
+
const reactModule = await import('react');
|
|
861
|
+
if (typeof reactModule.createElement !== "function") {
|
|
862
|
+
throw new Error("react createElement(...) export is unavailable");
|
|
863
|
+
}
|
|
864
|
+
return reactModule.createElement(
|
|
865
|
+
input.component,
|
|
866
|
+
input.props ?? {}
|
|
867
|
+
);
|
|
868
|
+
} catch (error) {
|
|
869
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
870
|
+
throw new Error(
|
|
871
|
+
`React Email component rendering requires react runtime support. Install react in your project. Loader error: ${message}`
|
|
872
|
+
);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
function createAuthReactEmailInput(component, props, overrides = {}) {
|
|
876
|
+
return {
|
|
877
|
+
...overrides,
|
|
878
|
+
component,
|
|
879
|
+
props
|
|
880
|
+
};
|
|
881
|
+
}
|
|
882
|
+
function defineAuthEmailTemplate(definition) {
|
|
883
|
+
const react = (props, overrides) => createAuthReactEmailInput(definition.component, props, {
|
|
884
|
+
...definition.defaults,
|
|
885
|
+
...overrides
|
|
886
|
+
});
|
|
887
|
+
return {
|
|
888
|
+
component: definition.component,
|
|
889
|
+
react,
|
|
890
|
+
toTemplateCreate: (input) => {
|
|
891
|
+
const templateKey = input.templateKey ?? definition.templateKey;
|
|
892
|
+
const subjectTemplate = input.subjectTemplate ?? definition.subjectTemplate;
|
|
893
|
+
if (!templateKey) {
|
|
894
|
+
throw new Error("defineAuthEmailTemplate.toTemplateCreate requires templateKey");
|
|
895
|
+
}
|
|
896
|
+
if (!subjectTemplate) {
|
|
897
|
+
throw new Error("defineAuthEmailTemplate.toTemplateCreate requires subjectTemplate");
|
|
898
|
+
}
|
|
899
|
+
const { props, react: reactOverrides, ...rest } = input;
|
|
900
|
+
return {
|
|
901
|
+
...rest,
|
|
902
|
+
templateKey,
|
|
903
|
+
subjectTemplate,
|
|
904
|
+
react: react(props, reactOverrides)
|
|
905
|
+
};
|
|
906
|
+
},
|
|
907
|
+
toTemplateUpdate: (input) => {
|
|
908
|
+
const { props, react: reactOverrides, ...rest } = input;
|
|
909
|
+
return {
|
|
910
|
+
...rest,
|
|
911
|
+
react: react(props, reactOverrides)
|
|
912
|
+
};
|
|
913
|
+
}
|
|
914
|
+
};
|
|
915
|
+
}
|
|
916
|
+
async function renderAthenaReactEmail(input, options) {
|
|
917
|
+
if (!isRecord2(input)) {
|
|
918
|
+
throw new Error("react email payload must be an object");
|
|
919
|
+
}
|
|
920
|
+
const runtimeOptions = mergeRuntimeOptions(options);
|
|
921
|
+
const start = Date.now();
|
|
922
|
+
emitReactEmailEvent(runtimeOptions?.observe, "render:start", {
|
|
923
|
+
route: runtimeOptions?.route,
|
|
924
|
+
message: "Rendering react email payload"
|
|
925
|
+
});
|
|
926
|
+
try {
|
|
927
|
+
const normalizedInput = mergeRenderDefaults(input, runtimeOptions?.defaults);
|
|
928
|
+
const element = await resolveReactEmailElement(normalizedInput);
|
|
929
|
+
const renderModule = await resolveReactEmailRenderModule();
|
|
930
|
+
const htmlValue = await renderModule.render(element);
|
|
931
|
+
const renderedHtml = typeof htmlValue === "string" ? htmlValue : String(htmlValue ?? "");
|
|
932
|
+
if (!renderedHtml.trim()) {
|
|
933
|
+
throw new Error("react email renderer returned an empty HTML string");
|
|
934
|
+
}
|
|
935
|
+
let html = renderedHtml;
|
|
936
|
+
if (normalizedInput.pretty && renderModule.pretty) {
|
|
937
|
+
const prettyValue = await renderModule.pretty(renderedHtml);
|
|
938
|
+
if (typeof prettyValue === "string" && prettyValue.trim().length > 0) {
|
|
939
|
+
html = prettyValue;
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
const explicitText = toStringOrUndefined(normalizedInput.text);
|
|
943
|
+
if (explicitText !== void 0) {
|
|
944
|
+
emitReactEmailEvent(runtimeOptions?.observe, "render:success", {
|
|
945
|
+
route: runtimeOptions?.route,
|
|
946
|
+
durationMs: Date.now() - start,
|
|
947
|
+
message: "Rendered react email with explicit text"
|
|
948
|
+
});
|
|
949
|
+
return {
|
|
950
|
+
html,
|
|
951
|
+
text: explicitText
|
|
952
|
+
};
|
|
953
|
+
}
|
|
954
|
+
if (normalizedInput.includePlainText === false || !renderModule.toPlainText) {
|
|
955
|
+
emitReactEmailEvent(runtimeOptions?.observe, "render:success", {
|
|
956
|
+
route: runtimeOptions?.route,
|
|
957
|
+
durationMs: Date.now() - start,
|
|
958
|
+
message: "Rendered react email without plain-text derivation"
|
|
959
|
+
});
|
|
960
|
+
return { html };
|
|
961
|
+
}
|
|
962
|
+
const plainTextValue = await renderModule.toPlainText(html);
|
|
963
|
+
const plainText = toStringOrUndefined(plainTextValue);
|
|
964
|
+
emitReactEmailEvent(runtimeOptions?.observe, "render:success", {
|
|
965
|
+
route: runtimeOptions?.route,
|
|
966
|
+
durationMs: Date.now() - start,
|
|
967
|
+
message: plainText ? "Rendered react email with derived plain text" : "Rendered react email HTML only"
|
|
968
|
+
});
|
|
969
|
+
if (plainText === void 0) {
|
|
970
|
+
return { html };
|
|
971
|
+
}
|
|
972
|
+
return {
|
|
973
|
+
html,
|
|
974
|
+
text: plainText
|
|
975
|
+
};
|
|
976
|
+
} catch (error) {
|
|
977
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
978
|
+
emitReactEmailEvent(runtimeOptions?.observe, "render:error", {
|
|
979
|
+
route: runtimeOptions?.route,
|
|
980
|
+
durationMs: Date.now() - start,
|
|
981
|
+
error: message,
|
|
982
|
+
message: "Failed to render react email payload"
|
|
983
|
+
});
|
|
984
|
+
throw error;
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
async function resolveReactEmailPayloadFields(input, fields, options) {
|
|
988
|
+
const { react, ...payloadWithoutReact } = input;
|
|
989
|
+
if (!react) {
|
|
990
|
+
return payloadWithoutReact;
|
|
991
|
+
}
|
|
992
|
+
const rendered = await renderAthenaReactEmail(react, options);
|
|
993
|
+
const payload = {
|
|
994
|
+
...payloadWithoutReact
|
|
995
|
+
};
|
|
996
|
+
payload[fields.htmlField] = rendered.html;
|
|
997
|
+
const currentTextValue = payload[fields.textField];
|
|
998
|
+
if (rendered.text !== void 0 && (currentTextValue === void 0 || currentTextValue === null || currentTextValue === "")) {
|
|
999
|
+
payload[fields.textField] = rendered.text;
|
|
1000
|
+
}
|
|
1001
|
+
if (fields.variablesField && (payload[fields.variablesField] === void 0 || payload[fields.variablesField] === null) && isRecord2(react.props)) {
|
|
1002
|
+
const derivedVariables = Object.keys(react.props);
|
|
1003
|
+
if (derivedVariables.length > 0) {
|
|
1004
|
+
payload[fields.variablesField] = derivedVariables;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
return payload;
|
|
1008
|
+
}
|
|
1009
|
+
|
|
500
1010
|
// src/auth/client.ts
|
|
501
1011
|
var DEFAULT_AUTH_BASE_URL = "http://localhost:3001/api/auth";
|
|
502
1012
|
var FALLBACK_SDK_VERSION2 = "1.0.0";
|
|
@@ -506,7 +1016,7 @@ var SDK_HEADER_VALUE2 = `${SDK_NAME2} ${SDK_VERSION2}`;
|
|
|
506
1016
|
function normalizeBaseUrl(baseUrl) {
|
|
507
1017
|
return (baseUrl ?? DEFAULT_AUTH_BASE_URL).replace(/\/$/, "");
|
|
508
1018
|
}
|
|
509
|
-
function
|
|
1019
|
+
function isRecord3(value) {
|
|
510
1020
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
511
1021
|
}
|
|
512
1022
|
function normalizeHeaderValue2(value) {
|
|
@@ -531,7 +1041,7 @@ function resolveRequestId2(headers) {
|
|
|
531
1041
|
return headers.get("x-request-id") ?? headers.get("x-correlation-id") ?? headers.get("x-athena-request-id") ?? void 0;
|
|
532
1042
|
}
|
|
533
1043
|
function resolveErrorMessage2(payload, fallback) {
|
|
534
|
-
if (
|
|
1044
|
+
if (isRecord3(payload)) {
|
|
535
1045
|
const messageCandidates = [payload.error, payload.message, payload.details];
|
|
536
1046
|
for (const candidate of messageCandidates) {
|
|
537
1047
|
if (typeof candidate === "string" && candidate.trim().length > 0) {
|
|
@@ -857,6 +1367,19 @@ function createAuthClient(config = {}) {
|
|
|
857
1367
|
options
|
|
858
1368
|
);
|
|
859
1369
|
};
|
|
1370
|
+
const withReactEmailRoute = (route) => ({
|
|
1371
|
+
...resolvedConfig.reactEmail,
|
|
1372
|
+
route
|
|
1373
|
+
});
|
|
1374
|
+
const resolveAdminEmailPayload = (route, input) => resolveReactEmailPayloadFields(input, {
|
|
1375
|
+
htmlField: "htmlBody",
|
|
1376
|
+
textField: "textBody"
|
|
1377
|
+
}, withReactEmailRoute(route));
|
|
1378
|
+
const resolveAdminEmailTemplatePayload = (route, input) => resolveReactEmailPayloadFields(input, {
|
|
1379
|
+
htmlField: "htmlTemplate",
|
|
1380
|
+
textField: "textTemplate",
|
|
1381
|
+
variablesField: "variables"
|
|
1382
|
+
}, withReactEmailRoute(route));
|
|
860
1383
|
const listUserEmailsWithFallback = async (input, options) => {
|
|
861
1384
|
const primary = await getWithQuery(
|
|
862
1385
|
"/email/list",
|
|
@@ -884,7 +1407,7 @@ function createAuthClient(config = {}) {
|
|
|
884
1407
|
data: null
|
|
885
1408
|
};
|
|
886
1409
|
}
|
|
887
|
-
const fallbackStatus =
|
|
1410
|
+
const fallbackStatus = isRecord3(fallback.data) && typeof fallback.data.ok === "boolean" ? fallback.data.ok ? "ok" : "error" : "ok";
|
|
888
1411
|
return {
|
|
889
1412
|
...fallback,
|
|
890
1413
|
data: {
|
|
@@ -1320,8 +1843,16 @@ function createAuthClient(config = {}) {
|
|
|
1320
1843
|
email: {
|
|
1321
1844
|
list: (input, options) => getWithQuery("/admin/email/list", input, options),
|
|
1322
1845
|
get: (input, options) => getWithQuery("/admin/email/get", input, options),
|
|
1323
|
-
create: (input, options) => postGeneric(
|
|
1324
|
-
|
|
1846
|
+
create: async (input, options) => postGeneric(
|
|
1847
|
+
"/admin/email/create",
|
|
1848
|
+
await resolveAdminEmailPayload("/admin/email/create", input),
|
|
1849
|
+
options
|
|
1850
|
+
),
|
|
1851
|
+
update: async (input, options) => postGeneric(
|
|
1852
|
+
"/admin/email/update",
|
|
1853
|
+
await resolveAdminEmailPayload("/admin/email/update", input),
|
|
1854
|
+
options
|
|
1855
|
+
),
|
|
1325
1856
|
delete: (input, options) => postGeneric("/admin/email/delete", input, options),
|
|
1326
1857
|
failure: {
|
|
1327
1858
|
list: (input, options) => getWithQuery("/admin/email-failure/list", input, options),
|
|
@@ -1333,17 +1864,33 @@ function createAuthClient(config = {}) {
|
|
|
1333
1864
|
template: {
|
|
1334
1865
|
list: (input, options) => getWithQuery("/admin/email-template/list", input, options),
|
|
1335
1866
|
get: (input, options) => getWithQuery("/admin/email-template/get", input, options),
|
|
1336
|
-
create: (input, options) => postGeneric(
|
|
1337
|
-
|
|
1867
|
+
create: async (input, options) => postGeneric(
|
|
1868
|
+
"/admin/email-template/create",
|
|
1869
|
+
await resolveAdminEmailTemplatePayload("/admin/email-template/create", input),
|
|
1870
|
+
options
|
|
1871
|
+
),
|
|
1872
|
+
update: async (input, options) => postGeneric(
|
|
1873
|
+
"/admin/email-template/update",
|
|
1874
|
+
await resolveAdminEmailTemplatePayload("/admin/email-template/update", input),
|
|
1875
|
+
options
|
|
1876
|
+
),
|
|
1338
1877
|
delete: (input, options) => postGeneric("/admin/email-template/delete", input, options)
|
|
1339
1878
|
}
|
|
1340
1879
|
},
|
|
1341
1880
|
emailTemplate: {
|
|
1342
1881
|
get: (input, options) => getWithQuery("/admin/email-template/get", input, options),
|
|
1343
|
-
create: (input, options) => postGeneric(
|
|
1882
|
+
create: async (input, options) => postGeneric(
|
|
1883
|
+
"/admin/email-template/create",
|
|
1884
|
+
await resolveAdminEmailTemplatePayload("/admin/email-template/create", input),
|
|
1885
|
+
options
|
|
1886
|
+
),
|
|
1344
1887
|
delete: (input, options) => postGeneric("/admin/email-template/delete", input, options),
|
|
1345
1888
|
list: (input, options) => getWithQuery("/admin/email-template/list", input, options),
|
|
1346
|
-
update: (input, options) => postGeneric(
|
|
1889
|
+
update: async (input, options) => postGeneric(
|
|
1890
|
+
"/admin/email-template/update",
|
|
1891
|
+
await resolveAdminEmailTemplatePayload("/admin/email-template/update", input),
|
|
1892
|
+
options
|
|
1893
|
+
)
|
|
1347
1894
|
}
|
|
1348
1895
|
},
|
|
1349
1896
|
apiKey: {
|
|
@@ -1535,6 +2082,19 @@ function createAuthClient(config = {}) {
|
|
|
1535
2082
|
};
|
|
1536
2083
|
}
|
|
1537
2084
|
|
|
2085
|
+
// src/utils/parse-boolean-flag.ts
|
|
2086
|
+
function parseBooleanFlag(rawValue, fallback) {
|
|
2087
|
+
if (!rawValue) return fallback;
|
|
2088
|
+
const normalized = rawValue.trim().toLowerCase();
|
|
2089
|
+
if (normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on") {
|
|
2090
|
+
return true;
|
|
2091
|
+
}
|
|
2092
|
+
if (normalized === "0" || normalized === "false" || normalized === "no" || normalized === "off") {
|
|
2093
|
+
return false;
|
|
2094
|
+
}
|
|
2095
|
+
return fallback;
|
|
2096
|
+
}
|
|
2097
|
+
|
|
1538
2098
|
// src/auxiliaries.ts
|
|
1539
2099
|
var AthenaErrorKind = {
|
|
1540
2100
|
UniqueViolation: "unique_violation",
|
|
@@ -1564,16 +2124,8 @@ var AthenaErrorCategory = {
|
|
|
1564
2124
|
Database: "database",
|
|
1565
2125
|
Unknown: "unknown"
|
|
1566
2126
|
};
|
|
1567
|
-
function
|
|
1568
|
-
|
|
1569
|
-
const normalized = rawValue.trim().toLowerCase();
|
|
1570
|
-
if (normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on") {
|
|
1571
|
-
return true;
|
|
1572
|
-
}
|
|
1573
|
-
if (normalized === "0" || normalized === "false" || normalized === "no" || normalized === "off") {
|
|
1574
|
-
return false;
|
|
1575
|
-
}
|
|
1576
|
-
return fallback;
|
|
2127
|
+
function parseBooleanFlag2(rawValue, fallback) {
|
|
2128
|
+
return parseBooleanFlag(rawValue, fallback);
|
|
1577
2129
|
}
|
|
1578
2130
|
var AthenaError = class extends Error {
|
|
1579
2131
|
code;
|
|
@@ -1597,10 +2149,39 @@ var AthenaError = class extends Error {
|
|
|
1597
2149
|
this.raw = input.raw;
|
|
1598
2150
|
}
|
|
1599
2151
|
};
|
|
1600
|
-
function
|
|
2152
|
+
function isRecord4(value) {
|
|
1601
2153
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
1602
2154
|
}
|
|
1603
|
-
function
|
|
2155
|
+
function firstNonEmptyString(...values) {
|
|
2156
|
+
for (const value of values) {
|
|
2157
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
2158
|
+
return value.trim();
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2161
|
+
return void 0;
|
|
2162
|
+
}
|
|
2163
|
+
function messageFromUnknownError(error) {
|
|
2164
|
+
if (typeof error === "string" && error.trim().length > 0) {
|
|
2165
|
+
return error.trim();
|
|
2166
|
+
}
|
|
2167
|
+
if (error instanceof Error && error.message.trim().length > 0) {
|
|
2168
|
+
return error.message.trim();
|
|
2169
|
+
}
|
|
2170
|
+
if (!isRecord4(error)) {
|
|
2171
|
+
return void 0;
|
|
2172
|
+
}
|
|
2173
|
+
return firstNonEmptyString(error.message, error.error, error.details);
|
|
2174
|
+
}
|
|
2175
|
+
function gatewayCodeFromUnknownError(error) {
|
|
2176
|
+
if (!isRecord4(error) || typeof error.gatewayCode !== "string") {
|
|
2177
|
+
return void 0;
|
|
2178
|
+
}
|
|
2179
|
+
return error.gatewayCode;
|
|
2180
|
+
}
|
|
2181
|
+
function isAthenaResultErrorLike(value) {
|
|
2182
|
+
return isRecord4(value) && typeof value.message === "string" && (value.athenaCode === void 0 || isAthenaErrorCode(value.athenaCode)) && (value.kind === void 0 || isAthenaErrorKind(value.kind)) && (value.category === void 0 || isAthenaErrorCategory(value.category)) && (value.retryable === void 0 || typeof value.retryable === "boolean") && (value.status === void 0 || typeof value.status === "number");
|
|
2183
|
+
}
|
|
2184
|
+
function isAthenaErrorKind(value) {
|
|
1604
2185
|
return value === "unique_violation" || value === "not_found" || value === "validation" || value === "auth" || value === "rate_limit" || value === "transient" || value === "unknown";
|
|
1605
2186
|
}
|
|
1606
2187
|
function isAthenaErrorCode(value) {
|
|
@@ -1610,7 +2191,7 @@ function isAthenaErrorCategory(value) {
|
|
|
1610
2191
|
return value === "transport" || value === "client" || value === "server" || value === "database" || value === "unknown";
|
|
1611
2192
|
}
|
|
1612
2193
|
function isNormalizedAthenaError(value) {
|
|
1613
|
-
return
|
|
2194
|
+
return isRecord4(value) && isAthenaErrorKind(value.kind) && isAthenaErrorCode(value.code) && isAthenaErrorCategory(value.category) && typeof value.retryable === "boolean" && typeof value.message === "string" && "raw" in value;
|
|
1614
2195
|
}
|
|
1615
2196
|
function withContextOverrides(normalized, context) {
|
|
1616
2197
|
if (!context?.table && !context?.operation) {
|
|
@@ -1623,7 +2204,7 @@ function withContextOverrides(normalized, context) {
|
|
|
1623
2204
|
};
|
|
1624
2205
|
}
|
|
1625
2206
|
function resolveAttachedNormalizedError(resultOrError) {
|
|
1626
|
-
if (!
|
|
2207
|
+
if (!isRecord4(resultOrError)) return void 0;
|
|
1627
2208
|
if (!("__athenaNormalizedError" in resultOrError)) return void 0;
|
|
1628
2209
|
const candidate = resultOrError.__athenaNormalizedError;
|
|
1629
2210
|
return isNormalizedAthenaError(candidate) ? candidate : void 0;
|
|
@@ -1642,7 +2223,7 @@ function contextHint(context) {
|
|
|
1642
2223
|
return `Identity: ${identity}`;
|
|
1643
2224
|
}
|
|
1644
2225
|
function isAthenaResultLike(value) {
|
|
1645
|
-
return
|
|
2226
|
+
return isRecord4(value) && "status" in value && "error" in value && "data" in value && typeof value.status === "number";
|
|
1646
2227
|
}
|
|
1647
2228
|
function operationFromDetails(details) {
|
|
1648
2229
|
if (!details?.endpoint) return void 0;
|
|
@@ -1684,6 +2265,7 @@ function classifyKind(status, code, message) {
|
|
|
1684
2265
|
if (status === 404 || hasNotFoundPattern) return "not_found";
|
|
1685
2266
|
if (status === 401 || status === 403 || hasAuthPattern) return "auth";
|
|
1686
2267
|
if (status === 429 || hasRateLimitPattern) return "rate_limit";
|
|
2268
|
+
if (code === "INVALID_URL") return "validation";
|
|
1687
2269
|
if (status === 400 || status === 422 || hasValidationPattern) return "validation";
|
|
1688
2270
|
if (code === "NETWORK_ERROR" || status === 0 || status !== void 0 && status >= 500 || hasTransientPattern) {
|
|
1689
2271
|
return "transient";
|
|
@@ -1691,6 +2273,9 @@ function classifyKind(status, code, message) {
|
|
|
1691
2273
|
return "unknown";
|
|
1692
2274
|
}
|
|
1693
2275
|
function toAthenaErrorCode(kind, status, gatewayCode) {
|
|
2276
|
+
if (gatewayCode === "INVALID_URL") {
|
|
2277
|
+
return AthenaErrorCode.ValidationFailed;
|
|
2278
|
+
}
|
|
1694
2279
|
if (gatewayCode === "NETWORK_ERROR" || kind === "transient" && status === 0) {
|
|
1695
2280
|
return AthenaErrorCode.NetworkUnavailable;
|
|
1696
2281
|
}
|
|
@@ -1739,15 +2324,16 @@ function toAthenaGatewayError(source, fallbackMessage, context) {
|
|
|
1739
2324
|
return source;
|
|
1740
2325
|
}
|
|
1741
2326
|
if (isAthenaResultLike(source) && source.errorDetails) {
|
|
2327
|
+
const message2 = messageFromUnknownError(source.error) ?? source.errorDetails.message ?? fallbackMessage;
|
|
1742
2328
|
return new AthenaGatewayError({
|
|
1743
2329
|
code: source.errorDetails.code,
|
|
1744
|
-
message:
|
|
2330
|
+
message: message2,
|
|
1745
2331
|
status: source.status,
|
|
1746
2332
|
endpoint: source.errorDetails.endpoint,
|
|
1747
2333
|
method: source.errorDetails.method,
|
|
1748
2334
|
requestId: source.errorDetails.requestId,
|
|
1749
|
-
hint: source.errorDetails.hint,
|
|
1750
|
-
cause: source.errorDetails.cause
|
|
2335
|
+
hint: (isRecord4(source.error) ? firstNonEmptyString(source.error.hint) : void 0) ?? source.errorDetails.hint,
|
|
2336
|
+
cause: (isRecord4(source.error) ? firstNonEmptyString(source.error.cause) : void 0) ?? source.errorDetails.cause
|
|
1751
2337
|
});
|
|
1752
2338
|
}
|
|
1753
2339
|
const normalized = normalizeAthenaError(source, context);
|
|
@@ -1769,13 +2355,50 @@ function normalizeAthenaError(resultOrError, context) {
|
|
|
1769
2355
|
return withContextOverrides(attached, context);
|
|
1770
2356
|
}
|
|
1771
2357
|
if (isAthenaResultLike(resultOrError)) {
|
|
2358
|
+
if (isAthenaResultErrorLike(resultOrError.error)) {
|
|
2359
|
+
return {
|
|
2360
|
+
kind: resultOrError.error.kind ?? classifyKind(resultOrError.status, gatewayCodeFromUnknownError(resultOrError.error), resultOrError.error.message),
|
|
2361
|
+
code: resultOrError.error.athenaCode ?? toAthenaErrorCode(
|
|
2362
|
+
resultOrError.error.kind ?? classifyKind(
|
|
2363
|
+
resultOrError.status,
|
|
2364
|
+
gatewayCodeFromUnknownError(resultOrError.error),
|
|
2365
|
+
resultOrError.error.message
|
|
2366
|
+
),
|
|
2367
|
+
resultOrError.error.status ?? resultOrError.status,
|
|
2368
|
+
gatewayCodeFromUnknownError(resultOrError.error)
|
|
2369
|
+
),
|
|
2370
|
+
category: resultOrError.error.category ?? toAthenaErrorCategory(
|
|
2371
|
+
resultOrError.error.kind ?? classifyKind(
|
|
2372
|
+
resultOrError.status,
|
|
2373
|
+
gatewayCodeFromUnknownError(resultOrError.error),
|
|
2374
|
+
resultOrError.error.message
|
|
2375
|
+
),
|
|
2376
|
+
resultOrError.error.status ?? resultOrError.status
|
|
2377
|
+
),
|
|
2378
|
+
retryable: resultOrError.error.retryable ?? isRetryable(
|
|
2379
|
+
resultOrError.error.kind ?? classifyKind(
|
|
2380
|
+
resultOrError.status,
|
|
2381
|
+
gatewayCodeFromUnknownError(resultOrError.error),
|
|
2382
|
+
resultOrError.error.message
|
|
2383
|
+
),
|
|
2384
|
+
resultOrError.error.status ?? resultOrError.status
|
|
2385
|
+
),
|
|
2386
|
+
status: resultOrError.error.status ?? resultOrError.status,
|
|
2387
|
+
constraint: resultOrError.error.constraint,
|
|
2388
|
+
table: context?.table ?? resultOrError.error.table,
|
|
2389
|
+
operation: context?.operation ?? resultOrError.error.operation,
|
|
2390
|
+
message: resultOrError.error.message,
|
|
2391
|
+
raw: resultOrError.error.raw ?? resultOrError.raw
|
|
2392
|
+
};
|
|
2393
|
+
}
|
|
1772
2394
|
const details = resultOrError.errorDetails;
|
|
1773
|
-
const message2 = resultOrError.error ?? details?.message ?? `Athena ${context?.operation ?? operationFromDetails(details) ?? "request"} failed`;
|
|
2395
|
+
const message2 = messageFromUnknownError(resultOrError.error) ?? details?.message ?? `Athena ${context?.operation ?? operationFromDetails(details) ?? "request"} failed`;
|
|
1774
2396
|
const operation = context?.operation ?? operationFromDetails(details);
|
|
1775
2397
|
const table = context?.table ?? extractTable(message2);
|
|
1776
2398
|
const constraint = extractConstraint(message2);
|
|
1777
|
-
const
|
|
1778
|
-
const
|
|
2399
|
+
const gatewayCode = details?.code ?? gatewayCodeFromUnknownError(resultOrError.error);
|
|
2400
|
+
const kind2 = classifyKind(resultOrError.status, gatewayCode, message2);
|
|
2401
|
+
const code = toAthenaErrorCode(kind2, resultOrError.status, gatewayCode);
|
|
1779
2402
|
const category = toAthenaErrorCategory(kind2, resultOrError.status);
|
|
1780
2403
|
return {
|
|
1781
2404
|
kind: kind2,
|
|
@@ -1812,7 +2435,7 @@ function normalizeAthenaError(resultOrError, context) {
|
|
|
1812
2435
|
};
|
|
1813
2436
|
}
|
|
1814
2437
|
if (resultOrError instanceof Error) {
|
|
1815
|
-
const maybeStatus =
|
|
2438
|
+
const maybeStatus = isRecord4(resultOrError) && typeof resultOrError.status === "number" ? resultOrError.status : void 0;
|
|
1816
2439
|
const kind2 = classifyKind(maybeStatus, void 0, resultOrError.message);
|
|
1817
2440
|
return {
|
|
1818
2441
|
kind: kind2,
|
|
@@ -2001,8 +2624,8 @@ async function withRetry(config, fn) {
|
|
|
2001
2624
|
// src/db/module.ts
|
|
2002
2625
|
function createDbModule(input) {
|
|
2003
2626
|
const db = {
|
|
2004
|
-
from(table) {
|
|
2005
|
-
return input.from(table);
|
|
2627
|
+
from(table, options) {
|
|
2628
|
+
return input.from(table, options);
|
|
2006
2629
|
},
|
|
2007
2630
|
select(table, columns, options) {
|
|
2008
2631
|
return input.from(table).select(columns, options);
|
|
@@ -2029,17 +2652,551 @@ function createDbModule(input) {
|
|
|
2029
2652
|
return db;
|
|
2030
2653
|
}
|
|
2031
2654
|
|
|
2655
|
+
// src/query-ast.ts
|
|
2656
|
+
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;
|
|
2657
|
+
var FILTER_OPERATORS = /* @__PURE__ */ new Set([
|
|
2658
|
+
"eq",
|
|
2659
|
+
"neq",
|
|
2660
|
+
"gt",
|
|
2661
|
+
"gte",
|
|
2662
|
+
"lt",
|
|
2663
|
+
"lte",
|
|
2664
|
+
"like",
|
|
2665
|
+
"ilike",
|
|
2666
|
+
"is",
|
|
2667
|
+
"in",
|
|
2668
|
+
"contains",
|
|
2669
|
+
"containedBy"
|
|
2670
|
+
]);
|
|
2671
|
+
var BOOLEAN_SAFE_OPERATORS = /* @__PURE__ */ new Set([
|
|
2672
|
+
"eq",
|
|
2673
|
+
"neq",
|
|
2674
|
+
"gt",
|
|
2675
|
+
"gte",
|
|
2676
|
+
"lt",
|
|
2677
|
+
"lte",
|
|
2678
|
+
"like",
|
|
2679
|
+
"ilike",
|
|
2680
|
+
"is"
|
|
2681
|
+
]);
|
|
2682
|
+
function isRecord5(value) {
|
|
2683
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
2684
|
+
}
|
|
2685
|
+
function isUuidString(value) {
|
|
2686
|
+
return UUID_PATTERN.test(value.trim());
|
|
2687
|
+
}
|
|
2688
|
+
function isUuidIdentifierColumn(column) {
|
|
2689
|
+
return column === "id" || /(?:^|_)uuid(?:_|$)/i.test(column) || /_id$/i.test(column);
|
|
2690
|
+
}
|
|
2691
|
+
function shouldUseUuidTextComparison(column, value) {
|
|
2692
|
+
return typeof value === "string" && isUuidString(value) && isUuidIdentifierColumn(column);
|
|
2693
|
+
}
|
|
2694
|
+
function isRelationSelectNode(value) {
|
|
2695
|
+
return isRecord5(value) && isRecord5(value.select);
|
|
2696
|
+
}
|
|
2697
|
+
function normalizeIdentifier(value, label) {
|
|
2698
|
+
const normalized = value.trim();
|
|
2699
|
+
if (!normalized) {
|
|
2700
|
+
throw new Error(`${label} must be a non-empty string`);
|
|
2701
|
+
}
|
|
2702
|
+
return normalized;
|
|
2703
|
+
}
|
|
2704
|
+
function stringifyFilterValue(value) {
|
|
2705
|
+
if (Array.isArray(value)) {
|
|
2706
|
+
return value.join(",");
|
|
2707
|
+
}
|
|
2708
|
+
return String(value);
|
|
2709
|
+
}
|
|
2710
|
+
function buildGatewayCondition(operator, column, value) {
|
|
2711
|
+
const condition = { operator };
|
|
2712
|
+
if (column) {
|
|
2713
|
+
condition.column = column;
|
|
2714
|
+
if (operator === "eq") {
|
|
2715
|
+
condition.eq_column = column;
|
|
2716
|
+
}
|
|
2717
|
+
}
|
|
2718
|
+
if (value !== void 0) {
|
|
2719
|
+
condition.value = value;
|
|
2720
|
+
if (operator === "eq") {
|
|
2721
|
+
condition.eq_value = value;
|
|
2722
|
+
}
|
|
2723
|
+
}
|
|
2724
|
+
if (operator === "eq" && column && value !== void 0 && shouldUseUuidTextComparison(column, value)) {
|
|
2725
|
+
condition.column_cast = "text";
|
|
2726
|
+
condition.eq_column_cast = "text";
|
|
2727
|
+
}
|
|
2728
|
+
return condition;
|
|
2729
|
+
}
|
|
2730
|
+
function compileRelationToken(key, node) {
|
|
2731
|
+
const nested = compileSelectShape(node.select);
|
|
2732
|
+
const propertyKey = normalizeIdentifier(key, "select relation key");
|
|
2733
|
+
if (node.schema && node.via) {
|
|
2734
|
+
throw new Error(
|
|
2735
|
+
`findMany relation "${propertyKey}" cannot combine schema and via yet; use schema with the relation key, or use via without schema`
|
|
2736
|
+
);
|
|
2737
|
+
}
|
|
2738
|
+
const relationTokenBase = normalizeIdentifier(node.via ?? propertyKey, "select relation token");
|
|
2739
|
+
if (node.schema && relationTokenBase.includes(".")) {
|
|
2740
|
+
throw new Error(
|
|
2741
|
+
`findMany relation "${propertyKey}" already resolves to a qualified relation token; do not also set schema`
|
|
2742
|
+
);
|
|
2743
|
+
}
|
|
2744
|
+
const relationSchema = node.schema?.trim();
|
|
2745
|
+
const relationToken = relationSchema ? `${normalizeIdentifier(relationSchema, "select relation schema")}.${relationTokenBase}` : relationTokenBase;
|
|
2746
|
+
const alias = node.as?.trim() || (relationToken !== propertyKey ? propertyKey : "");
|
|
2747
|
+
const prefix = alias ? `${alias}:` : "";
|
|
2748
|
+
return `${prefix}${relationToken}(${nested})`;
|
|
2749
|
+
}
|
|
2750
|
+
function compileSelectShape(select) {
|
|
2751
|
+
if (!isRecord5(select)) {
|
|
2752
|
+
throw new Error("findMany select must be an object");
|
|
2753
|
+
}
|
|
2754
|
+
const tokens = [];
|
|
2755
|
+
for (const [rawKey, rawValue] of Object.entries(select)) {
|
|
2756
|
+
if (rawValue === void 0) {
|
|
2757
|
+
continue;
|
|
2758
|
+
}
|
|
2759
|
+
if (rawValue === true) {
|
|
2760
|
+
tokens.push(normalizeIdentifier(rawKey, "select column"));
|
|
2761
|
+
continue;
|
|
2762
|
+
}
|
|
2763
|
+
if (isRelationSelectNode(rawValue)) {
|
|
2764
|
+
tokens.push(compileRelationToken(rawKey, rawValue));
|
|
2765
|
+
continue;
|
|
2766
|
+
}
|
|
2767
|
+
throw new Error(`Unsupported select node for "${rawKey}"`);
|
|
2768
|
+
}
|
|
2769
|
+
if (tokens.length === 0) {
|
|
2770
|
+
throw new Error("findMany select requires at least one field");
|
|
2771
|
+
}
|
|
2772
|
+
return tokens.join(",");
|
|
2773
|
+
}
|
|
2774
|
+
function selectShapeUsesRelationSchema(select) {
|
|
2775
|
+
if (!isRecord5(select)) {
|
|
2776
|
+
return false;
|
|
2777
|
+
}
|
|
2778
|
+
for (const rawValue of Object.values(select)) {
|
|
2779
|
+
if (!isRelationSelectNode(rawValue)) {
|
|
2780
|
+
continue;
|
|
2781
|
+
}
|
|
2782
|
+
if (typeof rawValue.schema === "string" && rawValue.schema.trim().length > 0) {
|
|
2783
|
+
return true;
|
|
2784
|
+
}
|
|
2785
|
+
if (selectShapeUsesRelationSchema(rawValue.select)) {
|
|
2786
|
+
return true;
|
|
2787
|
+
}
|
|
2788
|
+
}
|
|
2789
|
+
return false;
|
|
2790
|
+
}
|
|
2791
|
+
function compileColumnWhere(column, input) {
|
|
2792
|
+
const normalizedColumn = normalizeIdentifier(column, "where column");
|
|
2793
|
+
if (!isRecord5(input)) {
|
|
2794
|
+
return [buildGatewayCondition("eq", normalizedColumn, input)];
|
|
2795
|
+
}
|
|
2796
|
+
const conditions = [];
|
|
2797
|
+
for (const [rawOperator, rawValue] of Object.entries(input)) {
|
|
2798
|
+
if (rawValue === void 0) {
|
|
2799
|
+
continue;
|
|
2800
|
+
}
|
|
2801
|
+
if (!FILTER_OPERATORS.has(rawOperator)) {
|
|
2802
|
+
throw new Error(`Unsupported where operator "${rawOperator}" on "${normalizedColumn}"`);
|
|
2803
|
+
}
|
|
2804
|
+
if ((rawOperator === "in" || rawOperator === "contains" || rawOperator === "containedBy") && !Array.isArray(rawValue)) {
|
|
2805
|
+
throw new Error(`where.${normalizedColumn}.${rawOperator} requires an array value`);
|
|
2806
|
+
}
|
|
2807
|
+
conditions.push(
|
|
2808
|
+
buildGatewayCondition(
|
|
2809
|
+
rawOperator,
|
|
2810
|
+
normalizedColumn,
|
|
2811
|
+
rawValue
|
|
2812
|
+
)
|
|
2813
|
+
);
|
|
2814
|
+
}
|
|
2815
|
+
if (conditions.length === 0) {
|
|
2816
|
+
throw new Error(`where.${normalizedColumn} requires at least one operator`);
|
|
2817
|
+
}
|
|
2818
|
+
return conditions;
|
|
2819
|
+
}
|
|
2820
|
+
function compileBooleanExpressionTerms(clause, label) {
|
|
2821
|
+
if (!isRecord5(clause)) {
|
|
2822
|
+
throw new Error(`findMany where.${label} clauses must be objects`);
|
|
2823
|
+
}
|
|
2824
|
+
const entries = Object.entries(clause).filter(([, value]) => value !== void 0);
|
|
2825
|
+
if (entries.length !== 1) {
|
|
2826
|
+
throw new Error(`findMany where.${label} clauses must target exactly one column`);
|
|
2827
|
+
}
|
|
2828
|
+
const [rawColumn, rawValue] = entries[0];
|
|
2829
|
+
const column = normalizeIdentifier(rawColumn, `where.${label} column`);
|
|
2830
|
+
if (!isRecord5(rawValue)) {
|
|
2831
|
+
return [`${column}.eq.${stringifyFilterValue(rawValue)}`];
|
|
2832
|
+
}
|
|
2833
|
+
const operatorEntries = Object.entries(rawValue).filter(([, value]) => value !== void 0);
|
|
2834
|
+
if (operatorEntries.length === 0) {
|
|
2835
|
+
throw new Error(`findMany where.${label}.${column} requires at least one operator`);
|
|
2836
|
+
}
|
|
2837
|
+
if (label === "not" && operatorEntries.length > 1) {
|
|
2838
|
+
throw new Error("findMany where.not only supports a single lossless operator expression");
|
|
2839
|
+
}
|
|
2840
|
+
return operatorEntries.map(([rawOperator, rawOperand]) => {
|
|
2841
|
+
if (!BOOLEAN_SAFE_OPERATORS.has(rawOperator)) {
|
|
2842
|
+
throw new Error(`findMany where.${label} only supports lossless scalar operators`);
|
|
2843
|
+
}
|
|
2844
|
+
if (Array.isArray(rawOperand)) {
|
|
2845
|
+
throw new Error(`findMany where.${label} does not support array-valued operators`);
|
|
2846
|
+
}
|
|
2847
|
+
return `${column}.${rawOperator}.${stringifyFilterValue(rawOperand)}`;
|
|
2848
|
+
});
|
|
2849
|
+
}
|
|
2850
|
+
function compileWhere(where) {
|
|
2851
|
+
if (where === void 0) {
|
|
2852
|
+
return void 0;
|
|
2853
|
+
}
|
|
2854
|
+
if (!isRecord5(where)) {
|
|
2855
|
+
throw new Error("findMany where must be an object");
|
|
2856
|
+
}
|
|
2857
|
+
const conditions = [];
|
|
2858
|
+
for (const [rawKey, rawValue] of Object.entries(where)) {
|
|
2859
|
+
if (rawValue === void 0) {
|
|
2860
|
+
continue;
|
|
2861
|
+
}
|
|
2862
|
+
if (rawKey === "or") {
|
|
2863
|
+
if (!Array.isArray(rawValue) || rawValue.length === 0) {
|
|
2864
|
+
throw new Error("findMany where.or must be a non-empty array");
|
|
2865
|
+
}
|
|
2866
|
+
const expressions = rawValue.flatMap(
|
|
2867
|
+
(value) => compileBooleanExpressionTerms(value, "or")
|
|
2868
|
+
);
|
|
2869
|
+
conditions.push(buildGatewayCondition("or", void 0, expressions.join(",")));
|
|
2870
|
+
continue;
|
|
2871
|
+
}
|
|
2872
|
+
if (rawKey === "not") {
|
|
2873
|
+
const expressions = compileBooleanExpressionTerms(rawValue, "not");
|
|
2874
|
+
if (expressions.length !== 1) {
|
|
2875
|
+
throw new Error("findMany where.not must compile to exactly one lossless expression");
|
|
2876
|
+
}
|
|
2877
|
+
conditions.push(buildGatewayCondition("not", void 0, expressions[0]));
|
|
2878
|
+
continue;
|
|
2879
|
+
}
|
|
2880
|
+
conditions.push(...compileColumnWhere(rawKey, rawValue));
|
|
2881
|
+
}
|
|
2882
|
+
return conditions.length > 0 ? conditions : void 0;
|
|
2883
|
+
}
|
|
2884
|
+
function resolveOrderDirection(input) {
|
|
2885
|
+
if (typeof input === "boolean") {
|
|
2886
|
+
return input === false ? "descending" : "ascending";
|
|
2887
|
+
}
|
|
2888
|
+
if (typeof input === "string") {
|
|
2889
|
+
const normalized = input.trim().toLowerCase();
|
|
2890
|
+
if (normalized === "asc" || normalized === "ascending") {
|
|
2891
|
+
return "ascending";
|
|
2892
|
+
}
|
|
2893
|
+
if (normalized === "desc" || normalized === "descending") {
|
|
2894
|
+
return "descending";
|
|
2895
|
+
}
|
|
2896
|
+
throw new Error(`Unsupported orderBy direction "${input}"`);
|
|
2897
|
+
}
|
|
2898
|
+
return input.ascending === false ? "descending" : "ascending";
|
|
2899
|
+
}
|
|
2900
|
+
function compileOrderBy(orderBy) {
|
|
2901
|
+
if (orderBy === void 0) {
|
|
2902
|
+
return void 0;
|
|
2903
|
+
}
|
|
2904
|
+
if (!isRecord5(orderBy)) {
|
|
2905
|
+
throw new Error("findMany orderBy must be an object");
|
|
2906
|
+
}
|
|
2907
|
+
if ("column" in orderBy) {
|
|
2908
|
+
return {
|
|
2909
|
+
field: normalizeIdentifier(String(orderBy.column), "orderBy column"),
|
|
2910
|
+
direction: orderBy.ascending === false ? "descending" : "ascending"
|
|
2911
|
+
};
|
|
2912
|
+
}
|
|
2913
|
+
const entries = Object.entries(orderBy).filter(([, value]) => value !== void 0);
|
|
2914
|
+
if (entries.length === 0) {
|
|
2915
|
+
return void 0;
|
|
2916
|
+
}
|
|
2917
|
+
if (entries.length > 1) {
|
|
2918
|
+
throw new Error("findMany orderBy only supports a single column in v1");
|
|
2919
|
+
}
|
|
2920
|
+
const [column, input] = entries[0];
|
|
2921
|
+
return {
|
|
2922
|
+
field: normalizeIdentifier(column, "orderBy column"),
|
|
2923
|
+
direction: resolveOrderDirection(input)
|
|
2924
|
+
};
|
|
2925
|
+
}
|
|
2926
|
+
|
|
2927
|
+
// src/gateway/structured-select.ts
|
|
2928
|
+
var IDENTIFIER_SEGMENT_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
2929
|
+
function isIdentifierPath(value) {
|
|
2930
|
+
const segments = value.split(".").map((segment) => segment.trim());
|
|
2931
|
+
return segments.length > 1 && segments.every((segment) => IDENTIFIER_SEGMENT_PATTERN.test(segment));
|
|
2932
|
+
}
|
|
2933
|
+
function extractRelationHead(raw) {
|
|
2934
|
+
const trimmed = raw.trim();
|
|
2935
|
+
if (!trimmed) return "";
|
|
2936
|
+
const aliasIndex = trimmed.indexOf(":");
|
|
2937
|
+
const withoutAlias = aliasIndex >= 0 ? trimmed.slice(aliasIndex + 1).trim() : trimmed;
|
|
2938
|
+
const modifierIndex = withoutAlias.indexOf("!");
|
|
2939
|
+
return (modifierIndex >= 0 ? withoutAlias.slice(0, modifierIndex) : withoutAlias).trim();
|
|
2940
|
+
}
|
|
2941
|
+
function hasSchemaQualifiedRelationToken(select) {
|
|
2942
|
+
let singleQuoted = false;
|
|
2943
|
+
let doubleQuoted = false;
|
|
2944
|
+
let tokenStart = 0;
|
|
2945
|
+
for (let index = 0; index < select.length; index += 1) {
|
|
2946
|
+
const char = select[index];
|
|
2947
|
+
const next = index + 1 < select.length ? select[index + 1] : "";
|
|
2948
|
+
if (singleQuoted) {
|
|
2949
|
+
if (char === "'" && next === "'") {
|
|
2950
|
+
index += 1;
|
|
2951
|
+
continue;
|
|
2952
|
+
}
|
|
2953
|
+
if (char === "'") {
|
|
2954
|
+
singleQuoted = false;
|
|
2955
|
+
}
|
|
2956
|
+
continue;
|
|
2957
|
+
}
|
|
2958
|
+
if (doubleQuoted) {
|
|
2959
|
+
if (char === '"' && next === '"') {
|
|
2960
|
+
index += 1;
|
|
2961
|
+
continue;
|
|
2962
|
+
}
|
|
2963
|
+
if (char === '"') {
|
|
2964
|
+
doubleQuoted = false;
|
|
2965
|
+
}
|
|
2966
|
+
continue;
|
|
2967
|
+
}
|
|
2968
|
+
if (char === "'") {
|
|
2969
|
+
singleQuoted = true;
|
|
2970
|
+
continue;
|
|
2971
|
+
}
|
|
2972
|
+
if (char === '"') {
|
|
2973
|
+
doubleQuoted = true;
|
|
2974
|
+
continue;
|
|
2975
|
+
}
|
|
2976
|
+
if (char === "(") {
|
|
2977
|
+
const relationHead = extractRelationHead(select.slice(tokenStart, index));
|
|
2978
|
+
if (isIdentifierPath(relationHead)) {
|
|
2979
|
+
return true;
|
|
2980
|
+
}
|
|
2981
|
+
tokenStart = index + 1;
|
|
2982
|
+
continue;
|
|
2983
|
+
}
|
|
2984
|
+
if (char === "," || char === ")") {
|
|
2985
|
+
tokenStart = index + 1;
|
|
2986
|
+
}
|
|
2987
|
+
}
|
|
2988
|
+
return false;
|
|
2989
|
+
}
|
|
2990
|
+
function toStructuredSelectString(columns) {
|
|
2991
|
+
return Array.isArray(columns) ? columns.join(",") : columns;
|
|
2992
|
+
}
|
|
2993
|
+
function buildStructuredWhere(conditions) {
|
|
2994
|
+
if (!conditions?.length) return void 0;
|
|
2995
|
+
const where = {};
|
|
2996
|
+
for (const condition of conditions) {
|
|
2997
|
+
if (!condition.column) {
|
|
2998
|
+
return null;
|
|
2999
|
+
}
|
|
3000
|
+
if (condition.column_cast !== void 0 || condition.value_cast !== void 0) {
|
|
3001
|
+
return null;
|
|
3002
|
+
}
|
|
3003
|
+
const operand = condition.value;
|
|
3004
|
+
const operator = condition.operator;
|
|
3005
|
+
if (operator === "eq") {
|
|
3006
|
+
if (operand === void 0) return null;
|
|
3007
|
+
} else if (operator === "neq" || operator === "gt" || operator === "lt") {
|
|
3008
|
+
if (operand === void 0) return null;
|
|
3009
|
+
} else if (operator === "in") {
|
|
3010
|
+
if (!Array.isArray(operand)) return null;
|
|
3011
|
+
} else {
|
|
3012
|
+
return null;
|
|
3013
|
+
}
|
|
3014
|
+
const existing = where[condition.column];
|
|
3015
|
+
if (existing !== void 0 && (typeof existing !== "object" || existing === null || Array.isArray(existing))) {
|
|
3016
|
+
return null;
|
|
3017
|
+
}
|
|
3018
|
+
const next = existing ?? {};
|
|
3019
|
+
if (Object.prototype.hasOwnProperty.call(next, operator)) {
|
|
3020
|
+
return null;
|
|
3021
|
+
}
|
|
3022
|
+
next[operator] = operand;
|
|
3023
|
+
where[condition.column] = next;
|
|
3024
|
+
}
|
|
3025
|
+
return where;
|
|
3026
|
+
}
|
|
3027
|
+
function buildStructuredOrderBy(order) {
|
|
3028
|
+
if (!order?.field) return void 0;
|
|
3029
|
+
return {
|
|
3030
|
+
[order.field]: order.direction === "descending" ? "desc" : "asc"
|
|
3031
|
+
};
|
|
3032
|
+
}
|
|
3033
|
+
function buildStructuredSelectTransport(input) {
|
|
3034
|
+
const select = toStructuredSelectString(input.columns).trim();
|
|
3035
|
+
if (!select || select === "*") {
|
|
3036
|
+
return null;
|
|
3037
|
+
}
|
|
3038
|
+
if (!hasSchemaQualifiedRelationToken(select)) {
|
|
3039
|
+
return null;
|
|
3040
|
+
}
|
|
3041
|
+
if (input.count !== void 0 || input.head !== void 0) {
|
|
3042
|
+
return {
|
|
3043
|
+
error: "Schema-qualified nested select strings require structured select transport, which does not support count/head options in athena-js yet."
|
|
3044
|
+
};
|
|
3045
|
+
}
|
|
3046
|
+
const where = buildStructuredWhere(input.conditions);
|
|
3047
|
+
if (where === null) {
|
|
3048
|
+
return {
|
|
3049
|
+
error: "Schema-qualified nested select strings only support eq, neq, gt, lt, and in filters in athena-js structured select transport."
|
|
3050
|
+
};
|
|
3051
|
+
}
|
|
3052
|
+
return {
|
|
3053
|
+
select,
|
|
3054
|
+
payload: {
|
|
3055
|
+
table_name: input.tableName,
|
|
3056
|
+
select,
|
|
3057
|
+
where,
|
|
3058
|
+
orderBy: buildStructuredOrderBy(input.order),
|
|
3059
|
+
limit: input.limit,
|
|
3060
|
+
offset: input.offset,
|
|
3061
|
+
strip_nulls: input.stripNulls
|
|
3062
|
+
}
|
|
3063
|
+
};
|
|
3064
|
+
}
|
|
3065
|
+
|
|
3066
|
+
// src/query-transport.ts
|
|
3067
|
+
function canUseFindManyAstTransport(state) {
|
|
3068
|
+
return state.conditions.length === 0 && state.offset === void 0 && state.currentPage === void 0 && state.pageSize === void 0 && state.totalPages === void 0;
|
|
3069
|
+
}
|
|
3070
|
+
function toFindManyAstOrder(order) {
|
|
3071
|
+
if (!order) {
|
|
3072
|
+
return void 0;
|
|
3073
|
+
}
|
|
3074
|
+
return {
|
|
3075
|
+
column: order.field,
|
|
3076
|
+
ascending: order.direction !== "descending"
|
|
3077
|
+
};
|
|
3078
|
+
}
|
|
3079
|
+
function resolvePagination(input) {
|
|
3080
|
+
let limit = input.limit;
|
|
3081
|
+
let offset = input.offset;
|
|
3082
|
+
if (limit === void 0 && input.pageSize !== void 0) {
|
|
3083
|
+
limit = Math.max(0, Math.trunc(input.pageSize));
|
|
3084
|
+
}
|
|
3085
|
+
if (offset === void 0 && input.pageSize !== void 0 && input.currentPage !== void 0 && input.currentPage > 0) {
|
|
3086
|
+
offset = (Math.trunc(input.currentPage) - 1) * Math.max(0, Math.trunc(input.pageSize));
|
|
3087
|
+
}
|
|
3088
|
+
return { limit, offset };
|
|
3089
|
+
}
|
|
3090
|
+
function hasTypedEqualityComparison(conditions) {
|
|
3091
|
+
return conditions?.some(
|
|
3092
|
+
(condition) => condition.operator === "eq" && (condition.value_cast !== void 0 || condition.column_cast !== void 0)
|
|
3093
|
+
) ?? false;
|
|
3094
|
+
}
|
|
3095
|
+
function createSelectTransportPlan(input) {
|
|
3096
|
+
const conditions = input.state.conditions.length ? input.state.conditions.map((condition) => ({ ...condition })) : void 0;
|
|
3097
|
+
if (hasTypedEqualityComparison(conditions) && !input.options?.head && !input.options?.count && conditions) {
|
|
3098
|
+
const query = input.buildTypedSelectQuery({
|
|
3099
|
+
tableName: input.tableName,
|
|
3100
|
+
columns: input.columns,
|
|
3101
|
+
conditions,
|
|
3102
|
+
limit: input.state.limit,
|
|
3103
|
+
offset: input.state.offset,
|
|
3104
|
+
currentPage: input.state.currentPage,
|
|
3105
|
+
pageSize: input.state.pageSize,
|
|
3106
|
+
order: input.state.order
|
|
3107
|
+
});
|
|
3108
|
+
if (query) {
|
|
3109
|
+
return {
|
|
3110
|
+
kind: "query",
|
|
3111
|
+
query,
|
|
3112
|
+
payload: { query }
|
|
3113
|
+
};
|
|
3114
|
+
}
|
|
3115
|
+
}
|
|
3116
|
+
const pagination = resolvePagination({
|
|
3117
|
+
limit: input.state.limit,
|
|
3118
|
+
offset: input.state.offset,
|
|
3119
|
+
currentPage: input.state.currentPage,
|
|
3120
|
+
pageSize: input.state.pageSize
|
|
3121
|
+
});
|
|
3122
|
+
const stripNulls = input.options?.stripNulls ?? true;
|
|
3123
|
+
const structuredSelectTransport = buildStructuredSelectTransport({
|
|
3124
|
+
tableName: input.tableName,
|
|
3125
|
+
columns: input.columns,
|
|
3126
|
+
conditions,
|
|
3127
|
+
limit: pagination.limit,
|
|
3128
|
+
offset: pagination.offset,
|
|
3129
|
+
order: input.state.order,
|
|
3130
|
+
stripNulls,
|
|
3131
|
+
count: input.options?.count,
|
|
3132
|
+
head: input.options?.head
|
|
3133
|
+
});
|
|
3134
|
+
if (structuredSelectTransport && "error" in structuredSelectTransport) {
|
|
3135
|
+
throw new Error(structuredSelectTransport.error);
|
|
3136
|
+
}
|
|
3137
|
+
if (structuredSelectTransport) {
|
|
3138
|
+
const { payload, select } = structuredSelectTransport;
|
|
3139
|
+
return {
|
|
3140
|
+
kind: "fetch",
|
|
3141
|
+
payload,
|
|
3142
|
+
debug: {
|
|
3143
|
+
columns: select,
|
|
3144
|
+
conditions,
|
|
3145
|
+
limit: pagination.limit,
|
|
3146
|
+
offset: pagination.offset,
|
|
3147
|
+
order: input.state.order
|
|
3148
|
+
}
|
|
3149
|
+
};
|
|
3150
|
+
}
|
|
3151
|
+
return {
|
|
3152
|
+
kind: "fetch",
|
|
3153
|
+
payload: {
|
|
3154
|
+
table_name: input.tableName,
|
|
3155
|
+
columns: input.columns,
|
|
3156
|
+
conditions,
|
|
3157
|
+
limit: input.state.limit,
|
|
3158
|
+
offset: input.state.offset,
|
|
3159
|
+
current_page: input.state.currentPage,
|
|
3160
|
+
page_size: input.state.pageSize,
|
|
3161
|
+
total_pages: input.state.totalPages,
|
|
3162
|
+
sort_by: input.state.order,
|
|
3163
|
+
strip_nulls: stripNulls,
|
|
3164
|
+
count: input.options?.count,
|
|
3165
|
+
head: input.options?.head
|
|
3166
|
+
},
|
|
3167
|
+
debug: {
|
|
3168
|
+
columns: input.columns,
|
|
3169
|
+
conditions,
|
|
3170
|
+
limit: input.state.limit,
|
|
3171
|
+
offset: input.state.offset,
|
|
3172
|
+
currentPage: input.state.currentPage,
|
|
3173
|
+
pageSize: input.state.pageSize,
|
|
3174
|
+
order: input.state.order
|
|
3175
|
+
}
|
|
3176
|
+
};
|
|
3177
|
+
}
|
|
3178
|
+
|
|
2032
3179
|
// src/client.ts
|
|
2033
3180
|
var DEFAULT_COLUMNS = "*";
|
|
2034
|
-
var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
2035
3181
|
var SAFE_CAST_PATTERN = /^[a-z_][a-z0-9_]*(?:\[\])?$/i;
|
|
2036
3182
|
var ATHENA_NORMALIZED_ERROR_KEY = "__athenaNormalizedError";
|
|
3183
|
+
var QUERY_TRACE_STACK_SKIP_PATTERNS = [
|
|
3184
|
+
"src\\client.ts",
|
|
3185
|
+
"src/client.ts",
|
|
3186
|
+
"dist\\client.",
|
|
3187
|
+
"dist/client.",
|
|
3188
|
+
"node_modules\\@xylex-group\\athena",
|
|
3189
|
+
"node_modules/@xylex-group/athena",
|
|
3190
|
+
"node:internal",
|
|
3191
|
+
"internal/process"
|
|
3192
|
+
];
|
|
2037
3193
|
function formatResult(response) {
|
|
2038
3194
|
const result = {
|
|
2039
3195
|
data: response.data ?? null,
|
|
2040
|
-
error:
|
|
3196
|
+
error: null,
|
|
2041
3197
|
errorDetails: response.errorDetails ?? null,
|
|
2042
3198
|
status: response.status,
|
|
3199
|
+
statusText: response.statusText ?? null,
|
|
2043
3200
|
raw: response.raw
|
|
2044
3201
|
};
|
|
2045
3202
|
if (response.count !== void 0) {
|
|
@@ -2055,20 +3212,237 @@ function attachNormalizedError(result, normalizedError) {
|
|
|
2055
3212
|
writable: false
|
|
2056
3213
|
});
|
|
2057
3214
|
}
|
|
2058
|
-
function createResultFormatter(experimental) {
|
|
2059
|
-
|
|
2060
|
-
|
|
3215
|
+
function createResultFormatter(experimental) {
|
|
3216
|
+
return (response, context) => {
|
|
3217
|
+
const result = formatResult(response);
|
|
3218
|
+
if (response.error == null && response.errorDetails == null) {
|
|
3219
|
+
return result;
|
|
3220
|
+
}
|
|
3221
|
+
const normalizedError = normalizeAthenaError(
|
|
3222
|
+
{
|
|
3223
|
+
...result,
|
|
3224
|
+
error: response.error ?? response.errorDetails?.message ?? null
|
|
3225
|
+
},
|
|
3226
|
+
context
|
|
3227
|
+
);
|
|
3228
|
+
result.error = createResultError(response, result, normalizedError);
|
|
3229
|
+
attachNormalizedError(result, normalizedError);
|
|
3230
|
+
return result;
|
|
3231
|
+
};
|
|
3232
|
+
}
|
|
3233
|
+
function isRecord6(value) {
|
|
3234
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
3235
|
+
}
|
|
3236
|
+
function firstNonEmptyString2(...values) {
|
|
3237
|
+
for (const value of values) {
|
|
3238
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
3239
|
+
return value.trim();
|
|
3240
|
+
}
|
|
3241
|
+
}
|
|
3242
|
+
return void 0;
|
|
3243
|
+
}
|
|
3244
|
+
function resolveStructuredErrorPayload2(raw) {
|
|
3245
|
+
if (!isRecord6(raw)) return null;
|
|
3246
|
+
return isRecord6(raw.error) ? raw.error : raw;
|
|
3247
|
+
}
|
|
3248
|
+
function resolveStructuredErrorDetails(payload, message) {
|
|
3249
|
+
if (!payload || !("details" in payload)) {
|
|
3250
|
+
return null;
|
|
3251
|
+
}
|
|
3252
|
+
const details = payload.details;
|
|
3253
|
+
if (details == null) {
|
|
3254
|
+
return null;
|
|
3255
|
+
}
|
|
3256
|
+
if (typeof details === "string" && details.trim() === message.trim()) {
|
|
3257
|
+
return null;
|
|
3258
|
+
}
|
|
3259
|
+
return details;
|
|
3260
|
+
}
|
|
3261
|
+
function createResultError(response, result, normalized) {
|
|
3262
|
+
const rawRecord = isRecord6(response.raw) ? response.raw : null;
|
|
3263
|
+
const payload = resolveStructuredErrorPayload2(response.raw);
|
|
3264
|
+
const message = firstNonEmptyString2(
|
|
3265
|
+
response.error,
|
|
3266
|
+
payload?.message,
|
|
3267
|
+
payload?.error,
|
|
3268
|
+
payload?.details,
|
|
3269
|
+
response.errorDetails?.message,
|
|
3270
|
+
normalized.message
|
|
3271
|
+
) ?? normalized.message;
|
|
3272
|
+
const statusText = firstNonEmptyString2(response.statusText, rawRecord?.statusText) ?? null;
|
|
3273
|
+
const hint = firstNonEmptyString2(payload?.hint, response.errorDetails?.hint) ?? null;
|
|
3274
|
+
const code = firstNonEmptyString2(payload?.code) ?? normalized.code;
|
|
3275
|
+
const details = resolveStructuredErrorDetails(payload, message) ?? response.errorDetails?.cause ?? null;
|
|
3276
|
+
return {
|
|
3277
|
+
message,
|
|
3278
|
+
code,
|
|
3279
|
+
athenaCode: normalized.code,
|
|
3280
|
+
gatewayCode: response.errorDetails?.code ?? null,
|
|
3281
|
+
kind: normalized.kind,
|
|
3282
|
+
category: normalized.category,
|
|
3283
|
+
retryable: normalized.retryable,
|
|
3284
|
+
details,
|
|
3285
|
+
hint,
|
|
3286
|
+
status: result.status,
|
|
3287
|
+
statusText,
|
|
3288
|
+
constraint: normalized.constraint,
|
|
3289
|
+
table: normalized.table,
|
|
3290
|
+
operation: normalized.operation,
|
|
3291
|
+
endpoint: response.errorDetails?.endpoint,
|
|
3292
|
+
method: response.errorDetails?.method,
|
|
3293
|
+
requestId: response.errorDetails?.requestId,
|
|
3294
|
+
cause: response.errorDetails?.cause,
|
|
3295
|
+
raw: result.raw
|
|
3296
|
+
};
|
|
3297
|
+
}
|
|
3298
|
+
function parseQueryTraceCallsiteFrame(frame) {
|
|
3299
|
+
const trimmed = frame.trim();
|
|
3300
|
+
if (!trimmed) {
|
|
3301
|
+
return null;
|
|
3302
|
+
}
|
|
3303
|
+
let body = trimmed.replace(/^at\s+/, "");
|
|
3304
|
+
if (body.startsWith("async ")) {
|
|
3305
|
+
body = body.slice(6);
|
|
3306
|
+
}
|
|
3307
|
+
let functionName;
|
|
3308
|
+
let location = body;
|
|
3309
|
+
const wrappedMatch = body.match(/^(.*?)\s+\((.*)\)$/);
|
|
3310
|
+
if (wrappedMatch) {
|
|
3311
|
+
functionName = wrappedMatch[1].trim() || void 0;
|
|
3312
|
+
location = wrappedMatch[2].trim();
|
|
3313
|
+
}
|
|
3314
|
+
const locationMatch = location.match(/^(.*):(\d+):(\d+)$/);
|
|
3315
|
+
if (!locationMatch) {
|
|
3316
|
+
return null;
|
|
3317
|
+
}
|
|
3318
|
+
const filePath = locationMatch[1].replace(/^file:\/\//, "");
|
|
3319
|
+
const line = Number(locationMatch[2]);
|
|
3320
|
+
const column = Number(locationMatch[3]);
|
|
3321
|
+
if (!Number.isFinite(line) || !Number.isFinite(column)) {
|
|
3322
|
+
return null;
|
|
3323
|
+
}
|
|
3324
|
+
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
3325
|
+
const fileName = normalizedPath.split("/").at(-1) ?? filePath;
|
|
3326
|
+
return {
|
|
3327
|
+
filePath,
|
|
3328
|
+
fileName,
|
|
3329
|
+
line,
|
|
3330
|
+
column,
|
|
3331
|
+
frame: trimmed,
|
|
3332
|
+
functionName
|
|
3333
|
+
};
|
|
3334
|
+
}
|
|
3335
|
+
function captureQueryTraceCallsite() {
|
|
3336
|
+
const stack = new Error().stack;
|
|
3337
|
+
if (!stack) return null;
|
|
3338
|
+
const frames = stack.split("\n").slice(2).map((frame) => frame.trim()).filter(Boolean);
|
|
3339
|
+
for (const frame of frames) {
|
|
3340
|
+
if (QUERY_TRACE_STACK_SKIP_PATTERNS.some((pattern) => frame.includes(pattern))) {
|
|
3341
|
+
continue;
|
|
3342
|
+
}
|
|
3343
|
+
const callsite = parseQueryTraceCallsiteFrame(frame);
|
|
3344
|
+
if (callsite) return callsite;
|
|
3345
|
+
}
|
|
3346
|
+
const fallback = frames.find((frame) => !frame.includes("captureQueryTraceCallsite"));
|
|
3347
|
+
return fallback ? parseQueryTraceCallsiteFrame(fallback) : null;
|
|
3348
|
+
}
|
|
3349
|
+
function defaultQueryTraceLogger(event) {
|
|
3350
|
+
const target = event.table ?? event.functionName ?? "gateway";
|
|
3351
|
+
const outcomeState = event.outcome?.error ? "error" : "ok";
|
|
3352
|
+
const banner = `[athena-js][trace] ${event.operation.toUpperCase()} ${event.endpoint} ${target} ${event.durationMs}ms ${outcomeState}`;
|
|
3353
|
+
console.info(banner, event);
|
|
3354
|
+
}
|
|
3355
|
+
function captureTraceCallsite(tracer) {
|
|
3356
|
+
return tracer?.captureCallsite() ?? null;
|
|
3357
|
+
}
|
|
3358
|
+
function createTraceCallsiteStore(tracer, initialCallsite) {
|
|
3359
|
+
let storedCallsite = initialCallsite ?? void 0;
|
|
3360
|
+
return {
|
|
3361
|
+
resolve(callsite) {
|
|
3362
|
+
if (callsite) {
|
|
3363
|
+
storedCallsite = callsite;
|
|
3364
|
+
return callsite;
|
|
3365
|
+
}
|
|
3366
|
+
if (storedCallsite !== void 0) {
|
|
3367
|
+
return storedCallsite;
|
|
3368
|
+
}
|
|
3369
|
+
const capturedCallsite = captureTraceCallsite(tracer);
|
|
3370
|
+
if (capturedCallsite) {
|
|
3371
|
+
storedCallsite = capturedCallsite;
|
|
3372
|
+
}
|
|
3373
|
+
return capturedCallsite;
|
|
3374
|
+
}
|
|
3375
|
+
};
|
|
3376
|
+
}
|
|
3377
|
+
function createQueryTracer(experimental) {
|
|
3378
|
+
const traceOption = experimental?.traceQueries;
|
|
3379
|
+
if (!traceOption) {
|
|
3380
|
+
return void 0;
|
|
2061
3381
|
}
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
3382
|
+
const logger = typeof traceOption === "object" && traceOption.logger ? traceOption.logger : defaultQueryTraceLogger;
|
|
3383
|
+
const emit = (event) => {
|
|
3384
|
+
try {
|
|
3385
|
+
logger(event);
|
|
3386
|
+
} catch (error) {
|
|
3387
|
+
console.warn("[athena-js][trace] logger failed", error);
|
|
3388
|
+
}
|
|
3389
|
+
};
|
|
3390
|
+
return {
|
|
3391
|
+
captureCallsite: captureQueryTraceCallsite,
|
|
3392
|
+
publishSuccess(context, result, durationMs, callsite) {
|
|
3393
|
+
emit({
|
|
3394
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3395
|
+
durationMs,
|
|
3396
|
+
operation: context.operation,
|
|
3397
|
+
endpoint: context.endpoint,
|
|
3398
|
+
table: context.table,
|
|
3399
|
+
functionName: context.functionName,
|
|
3400
|
+
sql: context.sql,
|
|
3401
|
+
payload: context.payload,
|
|
3402
|
+
options: context.options,
|
|
3403
|
+
callsite,
|
|
3404
|
+
outcome: {
|
|
3405
|
+
status: result.status,
|
|
3406
|
+
error: result.error,
|
|
3407
|
+
errorDetails: result.errorDetails ?? null,
|
|
3408
|
+
count: result.count ?? null,
|
|
3409
|
+
data: result.data,
|
|
3410
|
+
raw: result.raw
|
|
3411
|
+
}
|
|
3412
|
+
});
|
|
3413
|
+
},
|
|
3414
|
+
publishFailure(context, error, durationMs, callsite) {
|
|
3415
|
+
emit({
|
|
3416
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3417
|
+
durationMs,
|
|
3418
|
+
operation: context.operation,
|
|
3419
|
+
endpoint: context.endpoint,
|
|
3420
|
+
table: context.table,
|
|
3421
|
+
functionName: context.functionName,
|
|
3422
|
+
sql: context.sql,
|
|
3423
|
+
payload: context.payload,
|
|
3424
|
+
options: context.options,
|
|
3425
|
+
callsite,
|
|
3426
|
+
thrownError: error
|
|
3427
|
+
});
|
|
2066
3428
|
}
|
|
2067
|
-
const normalizedError = normalizeAthenaError(result, context);
|
|
2068
|
-
attachNormalizedError(result, normalizedError);
|
|
2069
|
-
return result;
|
|
2070
3429
|
};
|
|
2071
3430
|
}
|
|
3431
|
+
async function executeWithQueryTrace(tracer, context, runner, callsiteOverride) {
|
|
3432
|
+
if (!tracer) {
|
|
3433
|
+
return runner();
|
|
3434
|
+
}
|
|
3435
|
+
const callsite = callsiteOverride ?? tracer.captureCallsite();
|
|
3436
|
+
const startedAt = Date.now();
|
|
3437
|
+
try {
|
|
3438
|
+
const result = await runner();
|
|
3439
|
+
tracer.publishSuccess(context, result, Date.now() - startedAt, callsite);
|
|
3440
|
+
return result;
|
|
3441
|
+
} catch (error) {
|
|
3442
|
+
tracer.publishFailure(context, error, Date.now() - startedAt, callsite);
|
|
3443
|
+
throw error;
|
|
3444
|
+
}
|
|
3445
|
+
}
|
|
2072
3446
|
function toSingleResult(response) {
|
|
2073
3447
|
const payload = response.data;
|
|
2074
3448
|
const singleData = Array.isArray(payload) ? payload.length ? payload[0] : null : payload ?? null;
|
|
@@ -2089,15 +3463,16 @@ function asAthenaJsonObject(value) {
|
|
|
2089
3463
|
function asAthenaJsonObjectArray(values) {
|
|
2090
3464
|
return values;
|
|
2091
3465
|
}
|
|
2092
|
-
function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS) {
|
|
3466
|
+
function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS, tracer, initialCallsite) {
|
|
2093
3467
|
let selectedColumns = defaultColumns === null ? void 0 : defaultColumns;
|
|
2094
3468
|
let selectedOptions;
|
|
2095
3469
|
let promise = null;
|
|
2096
|
-
const
|
|
3470
|
+
const callsiteStore = createTraceCallsiteStore(tracer, initialCallsite);
|
|
3471
|
+
const run = (columns, options, callsite) => {
|
|
2097
3472
|
const payloadColumns = columns ?? selectedColumns;
|
|
2098
3473
|
const payloadOptions = options ?? selectedOptions;
|
|
2099
3474
|
if (!promise) {
|
|
2100
|
-
promise = executor(payloadColumns, payloadOptions);
|
|
3475
|
+
promise = executor(payloadColumns, payloadOptions, callsiteStore.resolve(callsite));
|
|
2101
3476
|
}
|
|
2102
3477
|
return promise;
|
|
2103
3478
|
};
|
|
@@ -2105,7 +3480,7 @@ function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS) {
|
|
|
2105
3480
|
select(columns = selectedColumns, options) {
|
|
2106
3481
|
selectedColumns = columns;
|
|
2107
3482
|
selectedOptions = options ?? selectedOptions;
|
|
2108
|
-
return run(columns, options);
|
|
3483
|
+
return run(columns, options, captureTraceCallsite(tracer));
|
|
2109
3484
|
},
|
|
2110
3485
|
returning(columns = selectedColumns, options) {
|
|
2111
3486
|
return mutationQuery.select(columns, options);
|
|
@@ -2113,7 +3488,7 @@ function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS) {
|
|
|
2113
3488
|
single(columns = selectedColumns, options) {
|
|
2114
3489
|
selectedColumns = columns;
|
|
2115
3490
|
selectedOptions = options ?? selectedOptions;
|
|
2116
|
-
return run(columns, options).then(toSingleResult);
|
|
3491
|
+
return run(columns, options, captureTraceCallsite(tracer)).then(toSingleResult);
|
|
2117
3492
|
},
|
|
2118
3493
|
maybeSingle(columns = selectedColumns, options) {
|
|
2119
3494
|
return mutationQuery.single(columns, options);
|
|
@@ -2136,21 +3511,12 @@ function getResourceId(state) {
|
|
|
2136
3511
|
);
|
|
2137
3512
|
return candidate?.value?.toString();
|
|
2138
3513
|
}
|
|
2139
|
-
function
|
|
3514
|
+
function stringifyFilterValue2(value) {
|
|
2140
3515
|
if (Array.isArray(value)) {
|
|
2141
3516
|
return value.join(",");
|
|
2142
3517
|
}
|
|
2143
3518
|
return String(value);
|
|
2144
3519
|
}
|
|
2145
|
-
function isUuidString(value) {
|
|
2146
|
-
return UUID_PATTERN.test(value.trim());
|
|
2147
|
-
}
|
|
2148
|
-
function isUuidIdentifierColumn(column) {
|
|
2149
|
-
return column === "id" || /(?:^|_)uuid(?:_|$)/i.test(column) || /_id$/i.test(column);
|
|
2150
|
-
}
|
|
2151
|
-
function shouldUseUuidTextComparison(column, value) {
|
|
2152
|
-
return typeof value === "string" && isUuidString(value) && isUuidIdentifierColumn(column);
|
|
2153
|
-
}
|
|
2154
3520
|
function normalizeCast(cast) {
|
|
2155
3521
|
const normalized = cast.trim().toLowerCase();
|
|
2156
3522
|
if (!SAFE_CAST_PATTERN.test(normalized)) {
|
|
@@ -2173,25 +3539,92 @@ function withCast(expression, cast) {
|
|
|
2173
3539
|
}
|
|
2174
3540
|
function buildSelectColumnsClause(columns) {
|
|
2175
3541
|
if (Array.isArray(columns)) {
|
|
2176
|
-
return columns.map((column) =>
|
|
3542
|
+
return columns.map((column) => quoteSelectColumnToken(column)).join(", ");
|
|
2177
3543
|
}
|
|
2178
3544
|
return quoteSelectColumnsExpression(columns);
|
|
2179
3545
|
}
|
|
3546
|
+
function parseIdentifierSegment(input) {
|
|
3547
|
+
const trimmed = input.trim();
|
|
3548
|
+
if (!trimmed) return null;
|
|
3549
|
+
if (!trimmed.startsWith('"')) {
|
|
3550
|
+
return {
|
|
3551
|
+
normalizedValue: trimmed.toLowerCase()
|
|
3552
|
+
};
|
|
3553
|
+
}
|
|
3554
|
+
let value = "";
|
|
3555
|
+
let index = 1;
|
|
3556
|
+
let closed = false;
|
|
3557
|
+
while (index < trimmed.length) {
|
|
3558
|
+
const char = trimmed[index];
|
|
3559
|
+
const next = index + 1 < trimmed.length ? trimmed[index + 1] : "";
|
|
3560
|
+
if (char === '"' && next === '"') {
|
|
3561
|
+
value += '"';
|
|
3562
|
+
index += 2;
|
|
3563
|
+
continue;
|
|
3564
|
+
}
|
|
3565
|
+
if (char === '"') {
|
|
3566
|
+
closed = true;
|
|
3567
|
+
index += 1;
|
|
3568
|
+
break;
|
|
3569
|
+
}
|
|
3570
|
+
value += char;
|
|
3571
|
+
index += 1;
|
|
3572
|
+
}
|
|
3573
|
+
if (!closed || trimmed.slice(index).trim().length > 0 || !value.trim()) {
|
|
3574
|
+
return null;
|
|
3575
|
+
}
|
|
3576
|
+
return {
|
|
3577
|
+
normalizedValue: value
|
|
3578
|
+
};
|
|
3579
|
+
}
|
|
3580
|
+
function splitQualifiedTableName(tableName) {
|
|
3581
|
+
const trimmed = tableName.trim();
|
|
3582
|
+
let inQuotes = false;
|
|
3583
|
+
for (let index = 0; index < trimmed.length; index += 1) {
|
|
3584
|
+
const char = trimmed[index];
|
|
3585
|
+
const next = index + 1 < trimmed.length ? trimmed[index + 1] : "";
|
|
3586
|
+
if (char === '"') {
|
|
3587
|
+
if (inQuotes && next === '"') {
|
|
3588
|
+
index += 1;
|
|
3589
|
+
continue;
|
|
3590
|
+
}
|
|
3591
|
+
inQuotes = !inQuotes;
|
|
3592
|
+
continue;
|
|
3593
|
+
}
|
|
3594
|
+
if (char === "." && !inQuotes) {
|
|
3595
|
+
const schemaSegment = trimmed.slice(0, index).trim();
|
|
3596
|
+
const tableSegment = trimmed.slice(index + 1).trim();
|
|
3597
|
+
if (!schemaSegment || !tableSegment) {
|
|
3598
|
+
return null;
|
|
3599
|
+
}
|
|
3600
|
+
return { schemaSegment };
|
|
3601
|
+
}
|
|
3602
|
+
}
|
|
3603
|
+
return null;
|
|
3604
|
+
}
|
|
2180
3605
|
function resolveTableNameForCall(tableName, schema) {
|
|
2181
3606
|
if (!schema) return tableName;
|
|
2182
3607
|
const normalizedSchema = schema.trim();
|
|
2183
3608
|
if (!normalizedSchema) {
|
|
2184
3609
|
throw new Error("schema option must be a non-empty string");
|
|
2185
3610
|
}
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
3611
|
+
const normalizedTableName = tableName.trim();
|
|
3612
|
+
const parsedSchema = parseIdentifierSegment(normalizedSchema);
|
|
3613
|
+
if (!parsedSchema) {
|
|
3614
|
+
throw new Error("schema option must be a non-empty string");
|
|
3615
|
+
}
|
|
3616
|
+
const qualified = splitQualifiedTableName(normalizedTableName);
|
|
3617
|
+
if (qualified) {
|
|
3618
|
+
const parsedTableSchema = parseIdentifierSegment(qualified.schemaSegment);
|
|
3619
|
+
const sameSchema = parsedTableSchema ? parsedTableSchema.normalizedValue === parsedSchema.normalizedValue : normalizedTableName.startsWith(`${normalizedSchema}.`);
|
|
3620
|
+
if (sameSchema) {
|
|
3621
|
+
return normalizedTableName;
|
|
2189
3622
|
}
|
|
2190
3623
|
throw new Error(
|
|
2191
|
-
`schema option "${normalizedSchema}" conflicts with schema-qualified table "${
|
|
3624
|
+
`schema option "${normalizedSchema}" conflicts with schema-qualified table "${normalizedTableName}"`
|
|
2192
3625
|
);
|
|
2193
3626
|
}
|
|
2194
|
-
return `${normalizedSchema}.${
|
|
3627
|
+
return `${normalizedSchema}.${normalizedTableName}`;
|
|
2195
3628
|
}
|
|
2196
3629
|
function conditionToSqlClause(condition) {
|
|
2197
3630
|
if (!condition.column) return null;
|
|
@@ -2269,6 +3702,226 @@ function buildTypedSelectQuery(input) {
|
|
|
2269
3702
|
}
|
|
2270
3703
|
return `${sqlParts.join(" ")};`;
|
|
2271
3704
|
}
|
|
3705
|
+
function sanitizeSqlComment(comment) {
|
|
3706
|
+
return comment.replace(/\*\//g, "* /");
|
|
3707
|
+
}
|
|
3708
|
+
function toSqlJsonLiteral(value) {
|
|
3709
|
+
if (value === void 0) return "DEFAULT";
|
|
3710
|
+
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
3711
|
+
return toSqlLiteral(value);
|
|
3712
|
+
}
|
|
3713
|
+
return `'${escapeSqlStringLiteral(JSON.stringify(value))}'::jsonb`;
|
|
3714
|
+
}
|
|
3715
|
+
function conditionToDebugSqlClause(condition) {
|
|
3716
|
+
const exact = conditionToSqlClause(condition);
|
|
3717
|
+
if (exact) return exact;
|
|
3718
|
+
const rawCondition = sanitizeSqlComment(JSON.stringify(condition));
|
|
3719
|
+
if (!condition.column) {
|
|
3720
|
+
return `TRUE /* unsupported condition: ${rawCondition} */`;
|
|
3721
|
+
}
|
|
3722
|
+
const column = withCast(quoteQualifiedIdentifier(condition.column), condition.column_cast);
|
|
3723
|
+
const value = condition.value;
|
|
3724
|
+
const rhs = withCast(toSqlJsonLiteral(value), condition.value_cast);
|
|
3725
|
+
switch (condition.operator) {
|
|
3726
|
+
case "contains":
|
|
3727
|
+
return `${column} @> ${rhs}`;
|
|
3728
|
+
case "containedBy":
|
|
3729
|
+
return `${column} <@ ${rhs}`;
|
|
3730
|
+
case "not":
|
|
3731
|
+
return `TRUE /* NOT expression passthrough: ${rawCondition} */`;
|
|
3732
|
+
case "or":
|
|
3733
|
+
return `TRUE /* OR expression passthrough: ${rawCondition} */`;
|
|
3734
|
+
default:
|
|
3735
|
+
return `TRUE /* unsupported condition: ${rawCondition} */`;
|
|
3736
|
+
}
|
|
3737
|
+
}
|
|
3738
|
+
function appendOrderLimitOffset(sqlParts, order, limit, offset) {
|
|
3739
|
+
if (order?.field) {
|
|
3740
|
+
const direction = order.direction === "descending" ? "DESC" : "ASC";
|
|
3741
|
+
sqlParts.push(`ORDER BY ${quoteQualifiedIdentifier(order.field)} ${direction}`);
|
|
3742
|
+
}
|
|
3743
|
+
if (limit !== void 0) {
|
|
3744
|
+
sqlParts.push(`LIMIT ${Math.max(0, Math.trunc(limit))}`);
|
|
3745
|
+
}
|
|
3746
|
+
if (offset !== void 0) {
|
|
3747
|
+
sqlParts.push(`OFFSET ${Math.max(0, Math.trunc(offset))}`);
|
|
3748
|
+
}
|
|
3749
|
+
}
|
|
3750
|
+
function buildDebugSelectQuery(input) {
|
|
3751
|
+
const sqlParts = [
|
|
3752
|
+
`SELECT ${buildSelectColumnsClause(input.columns)} FROM ${quoteQualifiedIdentifier(input.tableName)}`
|
|
3753
|
+
];
|
|
3754
|
+
if (input.conditions?.length) {
|
|
3755
|
+
const whereClauses = input.conditions.map(conditionToDebugSqlClause);
|
|
3756
|
+
sqlParts.push(`WHERE ${whereClauses.join(" AND ")}`);
|
|
3757
|
+
}
|
|
3758
|
+
const pagination = resolvePagination(input);
|
|
3759
|
+
appendOrderLimitOffset(sqlParts, input.order, pagination.limit, pagination.offset);
|
|
3760
|
+
return `${sqlParts.join(" ")};`;
|
|
3761
|
+
}
|
|
3762
|
+
function resolveDebugTableIdentifier(tableName) {
|
|
3763
|
+
if (!tableName?.trim()) {
|
|
3764
|
+
return '"__unknown_table__"';
|
|
3765
|
+
}
|
|
3766
|
+
return quoteQualifiedIdentifier(tableName);
|
|
3767
|
+
}
|
|
3768
|
+
function buildInsertDebugSql(payload) {
|
|
3769
|
+
const rows = Array.isArray(payload.insert_body) ? payload.insert_body : [payload.insert_body];
|
|
3770
|
+
const columns = [];
|
|
3771
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3772
|
+
for (const row of rows) {
|
|
3773
|
+
for (const column of Object.keys(row)) {
|
|
3774
|
+
if (seen.has(column)) continue;
|
|
3775
|
+
seen.add(column);
|
|
3776
|
+
columns.push(column);
|
|
3777
|
+
}
|
|
3778
|
+
}
|
|
3779
|
+
const sqlParts = [`INSERT INTO ${quoteQualifiedIdentifier(payload.table_name)}`];
|
|
3780
|
+
if (!rows.length || !columns.length) {
|
|
3781
|
+
sqlParts.push("DEFAULT VALUES");
|
|
3782
|
+
if (rows.length > 1) {
|
|
3783
|
+
sqlParts.push(`/* trace: ${rows.length} rows collapsed to DEFAULT VALUES */`);
|
|
3784
|
+
}
|
|
3785
|
+
} else {
|
|
3786
|
+
const valuesClause = rows.map((row) => {
|
|
3787
|
+
const values = columns.map((column) => {
|
|
3788
|
+
const hasColumn = Object.prototype.hasOwnProperty.call(row, column);
|
|
3789
|
+
if (!hasColumn) {
|
|
3790
|
+
return payload.default_to_null ? "NULL" : "DEFAULT";
|
|
3791
|
+
}
|
|
3792
|
+
const rowValue = row[column];
|
|
3793
|
+
return toSqlJsonLiteral(rowValue);
|
|
3794
|
+
});
|
|
3795
|
+
return `(${values.join(", ")})`;
|
|
3796
|
+
}).join(", ");
|
|
3797
|
+
const columnClause = columns.map((column) => quoteQualifiedIdentifier(column)).join(", ");
|
|
3798
|
+
sqlParts.push(`(${columnClause})`);
|
|
3799
|
+
sqlParts.push(`VALUES ${valuesClause}`);
|
|
3800
|
+
}
|
|
3801
|
+
if (payload.on_conflict) {
|
|
3802
|
+
const conflictColumns = Array.isArray(payload.on_conflict) ? payload.on_conflict.map((column) => quoteQualifiedIdentifier(column)).join(", ") : payload.on_conflict;
|
|
3803
|
+
if (payload.update_body && Object.keys(payload.update_body).length > 0) {
|
|
3804
|
+
const assignments = Object.entries(payload.update_body).map(
|
|
3805
|
+
([column, value]) => `${quoteQualifiedIdentifier(column)} = ${toSqlJsonLiteral(value)}`
|
|
3806
|
+
);
|
|
3807
|
+
sqlParts.push(`ON CONFLICT (${conflictColumns}) DO UPDATE SET ${assignments.join(", ")}`);
|
|
3808
|
+
} else {
|
|
3809
|
+
sqlParts.push(`ON CONFLICT (${conflictColumns}) DO NOTHING`);
|
|
3810
|
+
}
|
|
3811
|
+
}
|
|
3812
|
+
if (payload.columns) {
|
|
3813
|
+
sqlParts.push(`RETURNING ${buildSelectColumnsClause(payload.columns)}`);
|
|
3814
|
+
}
|
|
3815
|
+
return `${sqlParts.join(" ")};`;
|
|
3816
|
+
}
|
|
3817
|
+
function buildUpdateDebugSql(payload) {
|
|
3818
|
+
const set = payload.set ?? payload.data ?? {};
|
|
3819
|
+
const assignments = Object.entries(set).map(
|
|
3820
|
+
([column, value]) => `${quoteQualifiedIdentifier(column)} = ${toSqlJsonLiteral(value)}`
|
|
3821
|
+
);
|
|
3822
|
+
const sqlParts = [
|
|
3823
|
+
`UPDATE ${resolveDebugTableIdentifier(payload.table_name)} SET ${assignments.length ? assignments.join(", ") : "/* empty set */"}`
|
|
3824
|
+
];
|
|
3825
|
+
if (payload.conditions?.length) {
|
|
3826
|
+
const whereClauses = payload.conditions.map(conditionToDebugSqlClause);
|
|
3827
|
+
sqlParts.push(`WHERE ${whereClauses.join(" AND ")}`);
|
|
3828
|
+
}
|
|
3829
|
+
const pagination = resolvePagination({
|
|
3830
|
+
currentPage: payload.current_page,
|
|
3831
|
+
pageSize: payload.page_size
|
|
3832
|
+
});
|
|
3833
|
+
appendOrderLimitOffset(sqlParts, payload.sort_by, pagination.limit, pagination.offset);
|
|
3834
|
+
if (payload.columns) {
|
|
3835
|
+
sqlParts.push(`RETURNING ${buildSelectColumnsClause(payload.columns)}`);
|
|
3836
|
+
}
|
|
3837
|
+
return `${sqlParts.join(" ")};`;
|
|
3838
|
+
}
|
|
3839
|
+
function buildDeleteDebugSql(payload) {
|
|
3840
|
+
const sqlParts = [`DELETE FROM ${quoteQualifiedIdentifier(payload.table_name)}`];
|
|
3841
|
+
const whereClauses = [];
|
|
3842
|
+
if (payload.resource_id) {
|
|
3843
|
+
whereClauses.push(`"resource_id" = ${toSqlLiteral(payload.resource_id)}`);
|
|
3844
|
+
}
|
|
3845
|
+
if (payload.conditions?.length) {
|
|
3846
|
+
whereClauses.push(...payload.conditions.map(conditionToDebugSqlClause));
|
|
3847
|
+
}
|
|
3848
|
+
if (whereClauses.length) {
|
|
3849
|
+
sqlParts.push(`WHERE ${whereClauses.join(" AND ")}`);
|
|
3850
|
+
}
|
|
3851
|
+
const pagination = resolvePagination({
|
|
3852
|
+
currentPage: payload.current_page,
|
|
3853
|
+
pageSize: payload.page_size
|
|
3854
|
+
});
|
|
3855
|
+
appendOrderLimitOffset(sqlParts, payload.sort_by, pagination.limit, pagination.offset);
|
|
3856
|
+
if (payload.columns) {
|
|
3857
|
+
sqlParts.push(`RETURNING ${buildSelectColumnsClause(payload.columns)}`);
|
|
3858
|
+
}
|
|
3859
|
+
return `${sqlParts.join(" ")};`;
|
|
3860
|
+
}
|
|
3861
|
+
function rpcFilterToSqlClause(filter) {
|
|
3862
|
+
const column = quoteQualifiedIdentifier(filter.column);
|
|
3863
|
+
const value = filter.value;
|
|
3864
|
+
switch (filter.operator) {
|
|
3865
|
+
case "eq":
|
|
3866
|
+
case "neq":
|
|
3867
|
+
case "gt":
|
|
3868
|
+
case "gte":
|
|
3869
|
+
case "lt":
|
|
3870
|
+
case "lte":
|
|
3871
|
+
case "like":
|
|
3872
|
+
case "ilike": {
|
|
3873
|
+
if (value === void 0 || Array.isArray(value)) {
|
|
3874
|
+
return `TRUE /* unsupported rpc filter: ${sanitizeSqlComment(JSON.stringify(filter))} */`;
|
|
3875
|
+
}
|
|
3876
|
+
const operatorMap = {
|
|
3877
|
+
eq: "=",
|
|
3878
|
+
neq: "!=",
|
|
3879
|
+
gt: ">",
|
|
3880
|
+
gte: ">=",
|
|
3881
|
+
lt: "<",
|
|
3882
|
+
lte: "<=",
|
|
3883
|
+
like: "LIKE",
|
|
3884
|
+
ilike: "ILIKE"
|
|
3885
|
+
};
|
|
3886
|
+
return `${column} ${operatorMap[filter.operator]} ${toSqlLiteral(value)}`;
|
|
3887
|
+
}
|
|
3888
|
+
case "is":
|
|
3889
|
+
if (value === null) return `${column} IS NULL`;
|
|
3890
|
+
if (value === true) return `${column} IS TRUE`;
|
|
3891
|
+
if (value === false) return `${column} IS FALSE`;
|
|
3892
|
+
return `TRUE /* unsupported rpc filter: ${sanitizeSqlComment(JSON.stringify(filter))} */`;
|
|
3893
|
+
case "in":
|
|
3894
|
+
if (!Array.isArray(value)) {
|
|
3895
|
+
return `TRUE /* unsupported rpc filter: ${sanitizeSqlComment(JSON.stringify(filter))} */`;
|
|
3896
|
+
}
|
|
3897
|
+
if (value.length === 0) return "FALSE";
|
|
3898
|
+
return `${column} IN (${value.map((item) => toSqlLiteral(item)).join(", ")})`;
|
|
3899
|
+
default:
|
|
3900
|
+
return `TRUE /* unsupported rpc filter: ${sanitizeSqlComment(JSON.stringify(filter))} */`;
|
|
3901
|
+
}
|
|
3902
|
+
}
|
|
3903
|
+
function buildRpcDebugSql(payload) {
|
|
3904
|
+
const argsEntries = payload.args ? Object.entries(payload.args) : [];
|
|
3905
|
+
const argsClause = argsEntries.map(([key, value]) => `${quoteQualifiedIdentifier(key)} => ${toSqlJsonLiteral(value)}`).join(", ");
|
|
3906
|
+
const functionRef = payload.schema ? `${quoteQualifiedIdentifier(payload.schema)}.${quoteQualifiedIdentifier(payload.function)}` : quoteQualifiedIdentifier(payload.function);
|
|
3907
|
+
const sqlParts = [
|
|
3908
|
+
`SELECT ${payload.select ? quoteSelectColumnsExpression(payload.select) : "*"} FROM ${functionRef}(${argsClause})`
|
|
3909
|
+
];
|
|
3910
|
+
if (payload.filters?.length) {
|
|
3911
|
+
sqlParts.push(`WHERE ${payload.filters.map(rpcFilterToSqlClause).join(" AND ")}`);
|
|
3912
|
+
}
|
|
3913
|
+
if (payload.order?.column) {
|
|
3914
|
+
const direction = payload.order.ascending === false ? "DESC" : "ASC";
|
|
3915
|
+
sqlParts.push(`ORDER BY ${quoteQualifiedIdentifier(payload.order.column)} ${direction}`);
|
|
3916
|
+
}
|
|
3917
|
+
if (payload.limit !== void 0) {
|
|
3918
|
+
sqlParts.push(`LIMIT ${Math.max(0, Math.trunc(payload.limit))}`);
|
|
3919
|
+
}
|
|
3920
|
+
if (payload.offset !== void 0) {
|
|
3921
|
+
sqlParts.push(`OFFSET ${Math.max(0, Math.trunc(payload.offset))}`);
|
|
3922
|
+
}
|
|
3923
|
+
return `${sqlParts.join(" ")};`;
|
|
3924
|
+
}
|
|
2272
3925
|
function createFilterMethods(state, addCondition, self) {
|
|
2273
3926
|
return {
|
|
2274
3927
|
eq(column, value) {
|
|
@@ -2380,7 +4033,7 @@ function createFilterMethods(state, addCondition, self) {
|
|
|
2380
4033
|
not(columnOrExpression, operator, value) {
|
|
2381
4034
|
const expression = String(columnOrExpression);
|
|
2382
4035
|
if (operator != null && value !== void 0) {
|
|
2383
|
-
addCondition("not", void 0, `${expression}.${operator}.${
|
|
4036
|
+
addCondition("not", void 0, `${expression}.${operator}.${stringifyFilterValue2(value)}`);
|
|
2384
4037
|
} else {
|
|
2385
4038
|
addCondition("not", void 0, expression);
|
|
2386
4039
|
}
|
|
@@ -2443,14 +4096,15 @@ function createRpcFilterMethods(filters, self) {
|
|
|
2443
4096
|
}
|
|
2444
4097
|
};
|
|
2445
4098
|
}
|
|
2446
|
-
function createRpcBuilder(functionName, args, baseOptions, client, formatGatewayResult) {
|
|
4099
|
+
function createRpcBuilder(functionName, args, baseOptions, client, formatGatewayResult, tracer, initialCallsite) {
|
|
2447
4100
|
const state = {
|
|
2448
4101
|
filters: []
|
|
2449
4102
|
};
|
|
2450
4103
|
let selectedColumns;
|
|
2451
4104
|
let selectedOptions;
|
|
2452
4105
|
let promise = null;
|
|
2453
|
-
const
|
|
4106
|
+
const callsiteStore = createTraceCallsiteStore(tracer, initialCallsite);
|
|
4107
|
+
const executeRpc = async (columns, options, callsite) => {
|
|
2454
4108
|
const mergedOptions = mergeOptions(baseOptions, options);
|
|
2455
4109
|
const payload = {
|
|
2456
4110
|
function: functionName,
|
|
@@ -2464,14 +4118,30 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
|
|
|
2464
4118
|
offset: state.offset,
|
|
2465
4119
|
order: state.order
|
|
2466
4120
|
};
|
|
2467
|
-
const
|
|
2468
|
-
|
|
4121
|
+
const endpoint = mergedOptions?.get ? `/rpc/${functionName}` : "/gateway/rpc";
|
|
4122
|
+
const sql = buildRpcDebugSql(payload);
|
|
4123
|
+
return executeWithQueryTrace(
|
|
4124
|
+
tracer,
|
|
4125
|
+
{
|
|
4126
|
+
operation: "rpc",
|
|
4127
|
+
endpoint,
|
|
4128
|
+
functionName,
|
|
4129
|
+
sql,
|
|
4130
|
+
payload,
|
|
4131
|
+
options: mergedOptions
|
|
4132
|
+
},
|
|
4133
|
+
async () => {
|
|
4134
|
+
const response = await client.rpcGateway(payload, mergedOptions);
|
|
4135
|
+
return formatGatewayResult(response, { operation: "rpc" });
|
|
4136
|
+
},
|
|
4137
|
+
callsite
|
|
4138
|
+
);
|
|
2469
4139
|
};
|
|
2470
|
-
const run = (columns, options) => {
|
|
4140
|
+
const run = (columns, options, callsite) => {
|
|
2471
4141
|
const payloadColumns = columns ?? selectedColumns;
|
|
2472
4142
|
const payloadOptions = options ?? selectedOptions;
|
|
2473
4143
|
if (!promise) {
|
|
2474
|
-
promise = executeRpc(payloadColumns, payloadOptions);
|
|
4144
|
+
promise = executeRpc(payloadColumns, payloadOptions, callsiteStore.resolve(callsite));
|
|
2475
4145
|
}
|
|
2476
4146
|
return promise;
|
|
2477
4147
|
};
|
|
@@ -2481,10 +4151,10 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
|
|
|
2481
4151
|
select(columns = selectedColumns, options) {
|
|
2482
4152
|
selectedColumns = columns;
|
|
2483
4153
|
selectedOptions = options ?? selectedOptions;
|
|
2484
|
-
return run(columns, options);
|
|
4154
|
+
return run(columns, options, captureTraceCallsite(tracer));
|
|
2485
4155
|
},
|
|
2486
4156
|
async single(columns, options) {
|
|
2487
|
-
const result = await run(columns, options);
|
|
4157
|
+
const result = await run(columns, options, captureTraceCallsite(tracer));
|
|
2488
4158
|
return toSingleResult(result);
|
|
2489
4159
|
},
|
|
2490
4160
|
maybeSingle(columns, options) {
|
|
@@ -2519,7 +4189,7 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
|
|
|
2519
4189
|
});
|
|
2520
4190
|
return builder;
|
|
2521
4191
|
}
|
|
2522
|
-
function createTableBuilder(tableName, client, formatGatewayResult) {
|
|
4192
|
+
function createTableBuilder(tableName, client, formatGatewayResult, tracer, experimental) {
|
|
2523
4193
|
const state = {
|
|
2524
4194
|
conditions: []
|
|
2525
4195
|
};
|
|
@@ -2551,70 +4221,103 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
|
|
|
2551
4221
|
}
|
|
2552
4222
|
state.conditions.push(condition);
|
|
2553
4223
|
};
|
|
4224
|
+
const snapshotState = () => ({
|
|
4225
|
+
conditions: state.conditions.map((condition) => ({ ...condition })),
|
|
4226
|
+
limit: state.limit,
|
|
4227
|
+
offset: state.offset,
|
|
4228
|
+
order: state.order ? { ...state.order } : void 0,
|
|
4229
|
+
currentPage: state.currentPage,
|
|
4230
|
+
pageSize: state.pageSize,
|
|
4231
|
+
totalPages: state.totalPages
|
|
4232
|
+
});
|
|
2554
4233
|
const builder = {};
|
|
2555
4234
|
const filterMethods = createFilterMethods(
|
|
2556
4235
|
state,
|
|
2557
4236
|
addCondition,
|
|
2558
4237
|
builder
|
|
2559
4238
|
);
|
|
2560
|
-
const runSelect = async (columns = DEFAULT_COLUMNS, options) => {
|
|
4239
|
+
const runSelect = async (columns = DEFAULT_COLUMNS, options, executionState = snapshotState(), callsite) => {
|
|
2561
4240
|
const resolvedTableName = resolveTableNameForCall(tableName, options?.schema);
|
|
2562
|
-
const
|
|
2563
|
-
|
|
2564
|
-
(condition) => condition.operator === "eq" && (condition.value_cast !== void 0 || condition.column_cast !== void 0)
|
|
2565
|
-
) ?? false;
|
|
2566
|
-
if (hasTypedEqualityComparison && !options?.head && !options?.count && conditions) {
|
|
2567
|
-
const query = buildTypedSelectQuery({
|
|
2568
|
-
tableName: resolvedTableName,
|
|
2569
|
-
columns,
|
|
2570
|
-
conditions,
|
|
2571
|
-
limit: state.limit,
|
|
2572
|
-
offset: state.offset,
|
|
2573
|
-
currentPage: state.currentPage,
|
|
2574
|
-
pageSize: state.pageSize,
|
|
2575
|
-
order: state.order
|
|
2576
|
-
});
|
|
2577
|
-
if (query) {
|
|
2578
|
-
const queryResponse = await client.queryGateway({ query }, options);
|
|
2579
|
-
return formatGatewayResult(queryResponse, { table: resolvedTableName, operation: "select" });
|
|
2580
|
-
}
|
|
2581
|
-
}
|
|
2582
|
-
const payload = {
|
|
2583
|
-
table_name: resolvedTableName,
|
|
4241
|
+
const plan = createSelectTransportPlan({
|
|
4242
|
+
tableName: resolvedTableName,
|
|
2584
4243
|
columns,
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
4244
|
+
state: executionState,
|
|
4245
|
+
options,
|
|
4246
|
+
buildTypedSelectQuery
|
|
4247
|
+
});
|
|
4248
|
+
if (plan.kind === "query") {
|
|
4249
|
+
return executeWithQueryTrace(
|
|
4250
|
+
tracer,
|
|
4251
|
+
{
|
|
4252
|
+
operation: "select",
|
|
4253
|
+
endpoint: "/gateway/query",
|
|
4254
|
+
table: resolvedTableName,
|
|
4255
|
+
sql: plan.query,
|
|
4256
|
+
payload: plan.payload,
|
|
4257
|
+
options
|
|
4258
|
+
},
|
|
4259
|
+
async () => {
|
|
4260
|
+
const queryResponse = await client.queryGateway(plan.payload, options);
|
|
4261
|
+
return formatGatewayResult(queryResponse, { table: resolvedTableName, operation: "select" });
|
|
4262
|
+
},
|
|
4263
|
+
callsite
|
|
4264
|
+
);
|
|
4265
|
+
}
|
|
4266
|
+
const sql = buildDebugSelectQuery({
|
|
4267
|
+
tableName: resolvedTableName,
|
|
4268
|
+
...plan.debug
|
|
4269
|
+
});
|
|
4270
|
+
return executeWithQueryTrace(
|
|
4271
|
+
tracer,
|
|
4272
|
+
{
|
|
4273
|
+
operation: "select",
|
|
4274
|
+
endpoint: "/gateway/fetch",
|
|
4275
|
+
table: resolvedTableName,
|
|
4276
|
+
sql,
|
|
4277
|
+
payload: plan.payload,
|
|
4278
|
+
options
|
|
4279
|
+
},
|
|
4280
|
+
async () => {
|
|
4281
|
+
const response = await client.fetchGateway(plan.payload, options);
|
|
4282
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
|
|
4283
|
+
},
|
|
4284
|
+
callsite
|
|
4285
|
+
);
|
|
2598
4286
|
};
|
|
2599
|
-
const createSelectChain = (columns, options) => {
|
|
4287
|
+
const createSelectChain = (columns, options, initialCallsite) => {
|
|
2600
4288
|
const chain = {};
|
|
4289
|
+
const callsiteStore = createTraceCallsiteStore(tracer, initialCallsite);
|
|
2601
4290
|
const filterMethods2 = createFilterMethods(state, addCondition, chain);
|
|
2602
4291
|
Object.assign(chain, filterMethods2, {
|
|
2603
4292
|
async single(cols, opts) {
|
|
2604
|
-
const r = await runSelect(
|
|
4293
|
+
const r = await runSelect(
|
|
4294
|
+
cols ?? columns,
|
|
4295
|
+
opts ?? options,
|
|
4296
|
+
snapshotState(),
|
|
4297
|
+
callsiteStore.resolve(captureTraceCallsite(tracer))
|
|
4298
|
+
);
|
|
2605
4299
|
return toSingleResult(r);
|
|
2606
4300
|
},
|
|
2607
4301
|
maybeSingle(cols, opts) {
|
|
2608
4302
|
return chain.single(cols, opts);
|
|
2609
4303
|
},
|
|
2610
4304
|
then(onfulfilled, onrejected) {
|
|
2611
|
-
return runSelect(
|
|
4305
|
+
return runSelect(
|
|
4306
|
+
columns,
|
|
4307
|
+
options,
|
|
4308
|
+
snapshotState(),
|
|
4309
|
+
callsiteStore.resolve()
|
|
4310
|
+
).then(onfulfilled, onrejected);
|
|
2612
4311
|
},
|
|
2613
4312
|
catch(onrejected) {
|
|
2614
|
-
return runSelect(columns, options).catch(
|
|
4313
|
+
return runSelect(columns, options, snapshotState(), callsiteStore.resolve()).catch(
|
|
4314
|
+
onrejected
|
|
4315
|
+
);
|
|
2615
4316
|
},
|
|
2616
4317
|
finally(onfinally) {
|
|
2617
|
-
return runSelect(columns, options).finally(
|
|
4318
|
+
return runSelect(columns, options, snapshotState(), callsiteStore.resolve()).finally(
|
|
4319
|
+
onfinally
|
|
4320
|
+
);
|
|
2618
4321
|
}
|
|
2619
4322
|
});
|
|
2620
4323
|
return chain;
|
|
@@ -2631,11 +4334,75 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
|
|
|
2631
4334
|
return builder;
|
|
2632
4335
|
},
|
|
2633
4336
|
select(columns = DEFAULT_COLUMNS, options) {
|
|
2634
|
-
return createSelectChain(columns, options);
|
|
4337
|
+
return createSelectChain(columns, options, captureTraceCallsite(tracer));
|
|
4338
|
+
},
|
|
4339
|
+
async findMany(options) {
|
|
4340
|
+
const columns = compileSelectShape(options.select);
|
|
4341
|
+
const baseState = snapshotState();
|
|
4342
|
+
const executionState = snapshotState();
|
|
4343
|
+
const callsite = captureTraceCallsite(tracer);
|
|
4344
|
+
const compiledWhere = compileWhere(options.where);
|
|
4345
|
+
if (compiledWhere?.length) {
|
|
4346
|
+
executionState.conditions.push(...compiledWhere);
|
|
4347
|
+
}
|
|
4348
|
+
if (options.orderBy !== void 0) {
|
|
4349
|
+
executionState.order = compileOrderBy(options.orderBy);
|
|
4350
|
+
}
|
|
4351
|
+
if (options.limit !== void 0) {
|
|
4352
|
+
executionState.limit = options.limit;
|
|
4353
|
+
}
|
|
4354
|
+
if (experimental?.findManyAst && canUseFindManyAstTransport(baseState) && !selectShapeUsesRelationSchema(options.select)) {
|
|
4355
|
+
const resolvedTableName = resolveTableNameForCall(tableName, void 0);
|
|
4356
|
+
const payload = {
|
|
4357
|
+
table_name: resolvedTableName,
|
|
4358
|
+
select: options.select
|
|
4359
|
+
};
|
|
4360
|
+
if (options.where !== void 0) {
|
|
4361
|
+
payload.where = options.where;
|
|
4362
|
+
}
|
|
4363
|
+
const astOrder = toFindManyAstOrder(executionState.order);
|
|
4364
|
+
if (astOrder !== void 0) {
|
|
4365
|
+
payload.orderBy = astOrder;
|
|
4366
|
+
}
|
|
4367
|
+
if (executionState.limit !== void 0) {
|
|
4368
|
+
payload.limit = executionState.limit;
|
|
4369
|
+
}
|
|
4370
|
+
const sql = buildDebugSelectQuery({
|
|
4371
|
+
tableName: resolvedTableName,
|
|
4372
|
+
columns,
|
|
4373
|
+
conditions: executionState.conditions,
|
|
4374
|
+
limit: executionState.limit,
|
|
4375
|
+
order: executionState.order
|
|
4376
|
+
});
|
|
4377
|
+
return executeWithQueryTrace(
|
|
4378
|
+
tracer,
|
|
4379
|
+
{
|
|
4380
|
+
operation: "select",
|
|
4381
|
+
endpoint: "/gateway/fetch",
|
|
4382
|
+
table: resolvedTableName,
|
|
4383
|
+
sql,
|
|
4384
|
+
payload
|
|
4385
|
+
},
|
|
4386
|
+
async () => {
|
|
4387
|
+
const response = await client.fetchGateway(
|
|
4388
|
+
payload
|
|
4389
|
+
);
|
|
4390
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
|
|
4391
|
+
},
|
|
4392
|
+
callsite
|
|
4393
|
+
);
|
|
4394
|
+
}
|
|
4395
|
+
return runSelect(
|
|
4396
|
+
columns,
|
|
4397
|
+
void 0,
|
|
4398
|
+
executionState,
|
|
4399
|
+
callsite
|
|
4400
|
+
);
|
|
2635
4401
|
},
|
|
2636
4402
|
insert(values, options) {
|
|
4403
|
+
const mutationCallsite = captureTraceCallsite(tracer);
|
|
2637
4404
|
if (Array.isArray(values)) {
|
|
2638
|
-
const executeInsertMany = async (columns, selectOptions) => {
|
|
4405
|
+
const executeInsertMany = async (columns, selectOptions, callsite) => {
|
|
2639
4406
|
const mergedOptions = mergeOptions(options, selectOptions);
|
|
2640
4407
|
const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
|
|
2641
4408
|
const payload = {
|
|
@@ -2648,12 +4415,27 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
|
|
|
2648
4415
|
if (mergedOptions?.defaultToNull !== void 0) {
|
|
2649
4416
|
payload.default_to_null = mergedOptions.defaultToNull;
|
|
2650
4417
|
}
|
|
2651
|
-
const
|
|
2652
|
-
return
|
|
4418
|
+
const sql = buildInsertDebugSql(payload);
|
|
4419
|
+
return executeWithQueryTrace(
|
|
4420
|
+
tracer,
|
|
4421
|
+
{
|
|
4422
|
+
operation: "insert",
|
|
4423
|
+
endpoint: "/gateway/insert",
|
|
4424
|
+
table: resolvedTableName,
|
|
4425
|
+
sql,
|
|
4426
|
+
payload,
|
|
4427
|
+
options: mergedOptions
|
|
4428
|
+
},
|
|
4429
|
+
async () => {
|
|
4430
|
+
const response = await client.insertGateway(payload, mergedOptions);
|
|
4431
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
|
|
4432
|
+
},
|
|
4433
|
+
callsite
|
|
4434
|
+
);
|
|
2653
4435
|
};
|
|
2654
|
-
return createMutationQuery(executeInsertMany);
|
|
4436
|
+
return createMutationQuery(executeInsertMany, DEFAULT_COLUMNS, tracer, mutationCallsite);
|
|
2655
4437
|
}
|
|
2656
|
-
const executeInsertOne = async (columns, selectOptions) => {
|
|
4438
|
+
const executeInsertOne = async (columns, selectOptions, callsite) => {
|
|
2657
4439
|
const mergedOptions = mergeOptions(options, selectOptions);
|
|
2658
4440
|
const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
|
|
2659
4441
|
const payload = {
|
|
@@ -2666,14 +4448,30 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
|
|
|
2666
4448
|
if (mergedOptions?.defaultToNull !== void 0) {
|
|
2667
4449
|
payload.default_to_null = mergedOptions.defaultToNull;
|
|
2668
4450
|
}
|
|
2669
|
-
const
|
|
2670
|
-
return
|
|
4451
|
+
const sql = buildInsertDebugSql(payload);
|
|
4452
|
+
return executeWithQueryTrace(
|
|
4453
|
+
tracer,
|
|
4454
|
+
{
|
|
4455
|
+
operation: "insert",
|
|
4456
|
+
endpoint: "/gateway/insert",
|
|
4457
|
+
table: resolvedTableName,
|
|
4458
|
+
sql,
|
|
4459
|
+
payload,
|
|
4460
|
+
options: mergedOptions
|
|
4461
|
+
},
|
|
4462
|
+
async () => {
|
|
4463
|
+
const response = await client.insertGateway(payload, mergedOptions);
|
|
4464
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
|
|
4465
|
+
},
|
|
4466
|
+
callsite
|
|
4467
|
+
);
|
|
2671
4468
|
};
|
|
2672
|
-
return createMutationQuery(executeInsertOne);
|
|
4469
|
+
return createMutationQuery(executeInsertOne, DEFAULT_COLUMNS, tracer, mutationCallsite);
|
|
2673
4470
|
},
|
|
2674
4471
|
upsert(values, options) {
|
|
4472
|
+
const mutationCallsite = captureTraceCallsite(tracer);
|
|
2675
4473
|
if (Array.isArray(values)) {
|
|
2676
|
-
const executeUpsertMany = async (columns, selectOptions) => {
|
|
4474
|
+
const executeUpsertMany = async (columns, selectOptions, callsite) => {
|
|
2677
4475
|
const mergedOptions = mergeOptions(options, selectOptions);
|
|
2678
4476
|
const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
|
|
2679
4477
|
const payload = {
|
|
@@ -2688,12 +4486,27 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
|
|
|
2688
4486
|
if (mergedOptions?.defaultToNull !== void 0) {
|
|
2689
4487
|
payload.default_to_null = mergedOptions.defaultToNull;
|
|
2690
4488
|
}
|
|
2691
|
-
const
|
|
2692
|
-
return
|
|
4489
|
+
const sql = buildInsertDebugSql(payload);
|
|
4490
|
+
return executeWithQueryTrace(
|
|
4491
|
+
tracer,
|
|
4492
|
+
{
|
|
4493
|
+
operation: "upsert",
|
|
4494
|
+
endpoint: "/gateway/insert",
|
|
4495
|
+
table: resolvedTableName,
|
|
4496
|
+
sql,
|
|
4497
|
+
payload,
|
|
4498
|
+
options: mergedOptions
|
|
4499
|
+
},
|
|
4500
|
+
async () => {
|
|
4501
|
+
const response = await client.insertGateway(payload, mergedOptions);
|
|
4502
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
|
|
4503
|
+
},
|
|
4504
|
+
callsite
|
|
4505
|
+
);
|
|
2693
4506
|
};
|
|
2694
|
-
return createMutationQuery(executeUpsertMany);
|
|
4507
|
+
return createMutationQuery(executeUpsertMany, DEFAULT_COLUMNS, tracer, mutationCallsite);
|
|
2695
4508
|
}
|
|
2696
|
-
const executeUpsertOne = async (columns, selectOptions) => {
|
|
4509
|
+
const executeUpsertOne = async (columns, selectOptions, callsite) => {
|
|
2697
4510
|
const mergedOptions = mergeOptions(options, selectOptions);
|
|
2698
4511
|
const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
|
|
2699
4512
|
const payload = {
|
|
@@ -2708,13 +4521,29 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
|
|
|
2708
4521
|
if (mergedOptions?.defaultToNull !== void 0) {
|
|
2709
4522
|
payload.default_to_null = mergedOptions.defaultToNull;
|
|
2710
4523
|
}
|
|
2711
|
-
const
|
|
2712
|
-
return
|
|
4524
|
+
const sql = buildInsertDebugSql(payload);
|
|
4525
|
+
return executeWithQueryTrace(
|
|
4526
|
+
tracer,
|
|
4527
|
+
{
|
|
4528
|
+
operation: "upsert",
|
|
4529
|
+
endpoint: "/gateway/insert",
|
|
4530
|
+
table: resolvedTableName,
|
|
4531
|
+
sql,
|
|
4532
|
+
payload,
|
|
4533
|
+
options: mergedOptions
|
|
4534
|
+
},
|
|
4535
|
+
async () => {
|
|
4536
|
+
const response = await client.insertGateway(payload, mergedOptions);
|
|
4537
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
|
|
4538
|
+
},
|
|
4539
|
+
callsite
|
|
4540
|
+
);
|
|
2713
4541
|
};
|
|
2714
|
-
return createMutationQuery(executeUpsertOne);
|
|
4542
|
+
return createMutationQuery(executeUpsertOne, DEFAULT_COLUMNS, tracer, mutationCallsite);
|
|
2715
4543
|
},
|
|
2716
4544
|
update(values, options) {
|
|
2717
|
-
const
|
|
4545
|
+
const mutationCallsite = captureTraceCallsite(tracer);
|
|
4546
|
+
const executeUpdate = async (columns, selectOptions, callsite) => {
|
|
2718
4547
|
const filters = state.conditions.length ? [...state.conditions] : void 0;
|
|
2719
4548
|
const mergedOptions = mergeOptions(options, selectOptions);
|
|
2720
4549
|
const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
|
|
@@ -2729,10 +4558,25 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
|
|
|
2729
4558
|
if (state.pageSize !== void 0) payload.page_size = state.pageSize;
|
|
2730
4559
|
if (state.totalPages !== void 0) payload.total_pages = state.totalPages;
|
|
2731
4560
|
if (columns) payload.columns = columns;
|
|
2732
|
-
const
|
|
2733
|
-
return
|
|
4561
|
+
const sql = buildUpdateDebugSql(payload);
|
|
4562
|
+
return executeWithQueryTrace(
|
|
4563
|
+
tracer,
|
|
4564
|
+
{
|
|
4565
|
+
operation: "update",
|
|
4566
|
+
endpoint: "/gateway/update",
|
|
4567
|
+
table: resolvedTableName,
|
|
4568
|
+
sql,
|
|
4569
|
+
payload,
|
|
4570
|
+
options: mergedOptions
|
|
4571
|
+
},
|
|
4572
|
+
async () => {
|
|
4573
|
+
const response = await client.updateGateway(payload, mergedOptions);
|
|
4574
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "update" });
|
|
4575
|
+
},
|
|
4576
|
+
callsite
|
|
4577
|
+
);
|
|
2734
4578
|
};
|
|
2735
|
-
const mutation = createMutationQuery(executeUpdate, null);
|
|
4579
|
+
const mutation = createMutationQuery(executeUpdate, null, tracer, mutationCallsite);
|
|
2736
4580
|
const updateChain = {};
|
|
2737
4581
|
const filterMethods2 = createFilterMethods(state, addCondition, updateChain);
|
|
2738
4582
|
Object.assign(updateChain, filterMethods2, mutation);
|
|
@@ -2744,7 +4588,8 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
|
|
|
2744
4588
|
if (!resourceId && !filters?.length) {
|
|
2745
4589
|
throw new Error('delete requires a resource_id either via eq("resource_id", ...) or options.resourceId');
|
|
2746
4590
|
}
|
|
2747
|
-
const
|
|
4591
|
+
const mutationCallsite = captureTraceCallsite(tracer);
|
|
4592
|
+
const executeDelete = async (columns, selectOptions, callsite) => {
|
|
2748
4593
|
const mergedOptions = mergeOptions(options, selectOptions);
|
|
2749
4594
|
const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
|
|
2750
4595
|
const payload = {
|
|
@@ -2757,13 +4602,33 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
|
|
|
2757
4602
|
if (state.pageSize !== void 0) payload.page_size = state.pageSize;
|
|
2758
4603
|
if (state.totalPages !== void 0) payload.total_pages = state.totalPages;
|
|
2759
4604
|
if (columns) payload.columns = columns;
|
|
2760
|
-
const
|
|
2761
|
-
return
|
|
4605
|
+
const sql = buildDeleteDebugSql(payload);
|
|
4606
|
+
return executeWithQueryTrace(
|
|
4607
|
+
tracer,
|
|
4608
|
+
{
|
|
4609
|
+
operation: "delete",
|
|
4610
|
+
endpoint: "/gateway/delete",
|
|
4611
|
+
table: resolvedTableName,
|
|
4612
|
+
sql,
|
|
4613
|
+
payload,
|
|
4614
|
+
options: mergedOptions
|
|
4615
|
+
},
|
|
4616
|
+
async () => {
|
|
4617
|
+
const response = await client.deleteGateway(payload, mergedOptions);
|
|
4618
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "delete" });
|
|
4619
|
+
},
|
|
4620
|
+
callsite
|
|
4621
|
+
);
|
|
2762
4622
|
};
|
|
2763
|
-
return createMutationQuery(executeDelete, null);
|
|
4623
|
+
return createMutationQuery(executeDelete, null, tracer, mutationCallsite);
|
|
2764
4624
|
},
|
|
2765
4625
|
async single(columns, options) {
|
|
2766
|
-
const response = await
|
|
4626
|
+
const response = await runSelect(
|
|
4627
|
+
columns ?? DEFAULT_COLUMNS,
|
|
4628
|
+
options,
|
|
4629
|
+
snapshotState(),
|
|
4630
|
+
captureTraceCallsite(tracer)
|
|
4631
|
+
);
|
|
2767
4632
|
return toSingleResult(response);
|
|
2768
4633
|
},
|
|
2769
4634
|
async maybeSingle(columns, options) {
|
|
@@ -2772,14 +4637,29 @@ function createTableBuilder(tableName, client, formatGatewayResult) {
|
|
|
2772
4637
|
});
|
|
2773
4638
|
return builder;
|
|
2774
4639
|
}
|
|
2775
|
-
function createQueryBuilder(client, formatGatewayResult) {
|
|
4640
|
+
function createQueryBuilder(client, formatGatewayResult, tracer) {
|
|
2776
4641
|
return async function query(query, options) {
|
|
2777
4642
|
const normalizedQuery = query.trim();
|
|
2778
4643
|
if (!normalizedQuery) {
|
|
2779
4644
|
throw new Error("query requires a non-empty string");
|
|
2780
4645
|
}
|
|
2781
|
-
const
|
|
2782
|
-
|
|
4646
|
+
const payload = { query: normalizedQuery };
|
|
4647
|
+
const callsite = captureTraceCallsite(tracer);
|
|
4648
|
+
return executeWithQueryTrace(
|
|
4649
|
+
tracer,
|
|
4650
|
+
{
|
|
4651
|
+
operation: "query",
|
|
4652
|
+
endpoint: "/gateway/query",
|
|
4653
|
+
sql: normalizedQuery,
|
|
4654
|
+
payload,
|
|
4655
|
+
options
|
|
4656
|
+
},
|
|
4657
|
+
async () => {
|
|
4658
|
+
const response = await client.queryGateway(payload, options);
|
|
4659
|
+
return formatGatewayResult(response, { operation: "query" });
|
|
4660
|
+
},
|
|
4661
|
+
callsite
|
|
4662
|
+
);
|
|
2783
4663
|
};
|
|
2784
4664
|
}
|
|
2785
4665
|
function createClientFromConfig(config) {
|
|
@@ -2791,8 +4671,15 @@ function createClientFromConfig(config) {
|
|
|
2791
4671
|
headers: config.headers
|
|
2792
4672
|
});
|
|
2793
4673
|
const formatGatewayResult = createResultFormatter(config.experimental);
|
|
4674
|
+
const queryTracer = createQueryTracer(config.experimental);
|
|
2794
4675
|
const auth = createAuthClient(config.auth);
|
|
2795
|
-
const from = (table) => createTableBuilder(
|
|
4676
|
+
const from = (table, options) => createTableBuilder(
|
|
4677
|
+
resolveTableNameForCall(table, options?.schema),
|
|
4678
|
+
gateway,
|
|
4679
|
+
formatGatewayResult,
|
|
4680
|
+
queryTracer,
|
|
4681
|
+
config.experimental
|
|
4682
|
+
);
|
|
2796
4683
|
const rpc = (fn, args, options) => {
|
|
2797
4684
|
const normalizedFn = fn.trim();
|
|
2798
4685
|
if (!normalizedFn) {
|
|
@@ -2803,16 +4690,19 @@ function createClientFromConfig(config) {
|
|
|
2803
4690
|
args,
|
|
2804
4691
|
options,
|
|
2805
4692
|
gateway,
|
|
2806
|
-
formatGatewayResult
|
|
4693
|
+
formatGatewayResult,
|
|
4694
|
+
queryTracer,
|
|
4695
|
+
captureTraceCallsite(queryTracer)
|
|
2807
4696
|
);
|
|
2808
4697
|
};
|
|
2809
|
-
const query = createQueryBuilder(gateway, formatGatewayResult);
|
|
4698
|
+
const query = createQueryBuilder(gateway, formatGatewayResult, queryTracer);
|
|
2810
4699
|
const db = createDbModule({ from, rpc, query });
|
|
2811
4700
|
return {
|
|
2812
4701
|
from,
|
|
2813
4702
|
db,
|
|
2814
4703
|
rpc,
|
|
2815
4704
|
query,
|
|
4705
|
+
verifyConnection: gateway.verifyConnection,
|
|
2816
4706
|
auth: auth.auth
|
|
2817
4707
|
};
|
|
2818
4708
|
}
|
|
@@ -2821,12 +4711,40 @@ function toBackendConfig(b) {
|
|
|
2821
4711
|
if (!b) return DEFAULT_BACKEND;
|
|
2822
4712
|
return typeof b === "string" ? { type: b } : b;
|
|
2823
4713
|
}
|
|
4714
|
+
function mergeAuthClientConfig(current, next) {
|
|
4715
|
+
const merged = {
|
|
4716
|
+
...current ?? {},
|
|
4717
|
+
...next
|
|
4718
|
+
};
|
|
4719
|
+
if (current?.headers || next.headers) {
|
|
4720
|
+
merged.headers = {
|
|
4721
|
+
...current?.headers ?? {},
|
|
4722
|
+
...next.headers ?? {}
|
|
4723
|
+
};
|
|
4724
|
+
}
|
|
4725
|
+
return merged;
|
|
4726
|
+
}
|
|
4727
|
+
function mergeExperimentalOptions(current, next) {
|
|
4728
|
+
const merged = {
|
|
4729
|
+
...current ?? {},
|
|
4730
|
+
...next
|
|
4731
|
+
};
|
|
4732
|
+
if (current?.traceQueries && typeof current.traceQueries === "object" && next.traceQueries && typeof next.traceQueries === "object") {
|
|
4733
|
+
merged.traceQueries = {
|
|
4734
|
+
...current.traceQueries,
|
|
4735
|
+
...next.traceQueries
|
|
4736
|
+
};
|
|
4737
|
+
}
|
|
4738
|
+
return merged;
|
|
4739
|
+
}
|
|
2824
4740
|
var AthenaClientBuilderImpl = class {
|
|
2825
4741
|
baseUrl;
|
|
2826
4742
|
apiKey;
|
|
2827
4743
|
backendConfig = DEFAULT_BACKEND;
|
|
2828
4744
|
clientName;
|
|
2829
4745
|
defaultHeaders;
|
|
4746
|
+
authConfig;
|
|
4747
|
+
experimentalOptions;
|
|
2830
4748
|
isHealthTrackingEnabled = false;
|
|
2831
4749
|
url(url) {
|
|
2832
4750
|
this.baseUrl = url;
|
|
@@ -2848,6 +4766,35 @@ var AthenaClientBuilderImpl = class {
|
|
|
2848
4766
|
this.defaultHeaders = headers;
|
|
2849
4767
|
return this;
|
|
2850
4768
|
}
|
|
4769
|
+
auth(config) {
|
|
4770
|
+
this.authConfig = mergeAuthClientConfig(this.authConfig, config);
|
|
4771
|
+
return this;
|
|
4772
|
+
}
|
|
4773
|
+
experimental(options) {
|
|
4774
|
+
this.experimentalOptions = mergeExperimentalOptions(this.experimentalOptions, options);
|
|
4775
|
+
return this;
|
|
4776
|
+
}
|
|
4777
|
+
options(options) {
|
|
4778
|
+
if (options.client !== void 0) {
|
|
4779
|
+
this.clientName = options.client;
|
|
4780
|
+
}
|
|
4781
|
+
if (options.backend !== void 0) {
|
|
4782
|
+
this.backendConfig = toBackendConfig(options.backend);
|
|
4783
|
+
}
|
|
4784
|
+
if (options.headers !== void 0) {
|
|
4785
|
+
this.defaultHeaders = {
|
|
4786
|
+
...this.defaultHeaders ?? {},
|
|
4787
|
+
...options.headers
|
|
4788
|
+
};
|
|
4789
|
+
}
|
|
4790
|
+
if (options.auth !== void 0) {
|
|
4791
|
+
this.authConfig = mergeAuthClientConfig(this.authConfig, options.auth);
|
|
4792
|
+
}
|
|
4793
|
+
if (options.experimental !== void 0) {
|
|
4794
|
+
this.experimentalOptions = mergeExperimentalOptions(this.experimentalOptions, options.experimental);
|
|
4795
|
+
}
|
|
4796
|
+
return this;
|
|
4797
|
+
}
|
|
2851
4798
|
healthTracking(enabled) {
|
|
2852
4799
|
this.isHealthTrackingEnabled = enabled;
|
|
2853
4800
|
return this;
|
|
@@ -2862,7 +4809,9 @@ var AthenaClientBuilderImpl = class {
|
|
|
2862
4809
|
client: this.clientName,
|
|
2863
4810
|
backend: this.backendConfig,
|
|
2864
4811
|
headers: this.defaultHeaders,
|
|
2865
|
-
healthTracking: this.isHealthTrackingEnabled
|
|
4812
|
+
healthTracking: this.isHealthTrackingEnabled,
|
|
4813
|
+
auth: this.authConfig,
|
|
4814
|
+
experimental: this.experimentalOptions
|
|
2866
4815
|
});
|
|
2867
4816
|
}
|
|
2868
4817
|
};
|
|
@@ -2997,8 +4946,8 @@ var TypedAthenaClientImpl = class _TypedAthenaClientImpl {
|
|
|
2997
4946
|
});
|
|
2998
4947
|
this.db = this.baseClient.db;
|
|
2999
4948
|
}
|
|
3000
|
-
from(table) {
|
|
3001
|
-
return this.baseClient.from(table);
|
|
4949
|
+
from(table, options) {
|
|
4950
|
+
return this.baseClient.from(table, options);
|
|
3002
4951
|
}
|
|
3003
4952
|
rpc(fn, args, options) {
|
|
3004
4953
|
return this.baseClient.rpc(fn, args, options);
|
|
@@ -3006,6 +4955,9 @@ var TypedAthenaClientImpl = class _TypedAthenaClientImpl {
|
|
|
3006
4955
|
query(query, options) {
|
|
3007
4956
|
return this.baseClient.query(query, options);
|
|
3008
4957
|
}
|
|
4958
|
+
verifyConnection(options) {
|
|
4959
|
+
return this.baseClient.verifyConnection(options);
|
|
4960
|
+
}
|
|
3009
4961
|
withTenantContext(context) {
|
|
3010
4962
|
return new _TypedAthenaClientImpl({
|
|
3011
4963
|
registry: this.registry,
|
|
@@ -3042,7 +4994,7 @@ function resolveNullishValue(mode) {
|
|
|
3042
4994
|
if (mode === "null") return null;
|
|
3043
4995
|
return "";
|
|
3044
4996
|
}
|
|
3045
|
-
function
|
|
4997
|
+
function isRecord7(value) {
|
|
3046
4998
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
3047
4999
|
}
|
|
3048
5000
|
function isNullableColumn(model, key) {
|
|
@@ -3051,7 +5003,7 @@ function isNullableColumn(model, key) {
|
|
|
3051
5003
|
}
|
|
3052
5004
|
function toModelFormDefaults(model, values, options) {
|
|
3053
5005
|
const source = values;
|
|
3054
|
-
if (!
|
|
5006
|
+
if (!isRecord7(source)) {
|
|
3055
5007
|
return {};
|
|
3056
5008
|
}
|
|
3057
5009
|
const mode = options?.nullishMode ?? "empty-string";
|
|
@@ -3248,28 +5200,28 @@ function throwBrowserUnsupported(apiName) {
|
|
|
3248
5200
|
`@xylex-group/athena: ${apiName} is not available in browser bundles. Use this API in a Node.js runtime.`
|
|
3249
5201
|
);
|
|
3250
5202
|
}
|
|
3251
|
-
function createPostgresIntrospectionProvider(
|
|
5203
|
+
function createPostgresIntrospectionProvider(options) {
|
|
3252
5204
|
return throwBrowserUnsupported("createPostgresIntrospectionProvider");
|
|
3253
5205
|
}
|
|
3254
5206
|
function defineGeneratorConfig(config) {
|
|
3255
5207
|
return config;
|
|
3256
5208
|
}
|
|
3257
|
-
function findGeneratorConfigPath(
|
|
5209
|
+
function findGeneratorConfigPath(cwd) {
|
|
3258
5210
|
return throwBrowserUnsupported("findGeneratorConfigPath");
|
|
3259
5211
|
}
|
|
3260
|
-
async function loadGeneratorConfig(
|
|
5212
|
+
async function loadGeneratorConfig(options = {}) {
|
|
3261
5213
|
return throwBrowserUnsupported("loadGeneratorConfig");
|
|
3262
5214
|
}
|
|
3263
|
-
function normalizeGeneratorConfig(
|
|
5215
|
+
function normalizeGeneratorConfig(input) {
|
|
3264
5216
|
return throwBrowserUnsupported("normalizeGeneratorConfig");
|
|
3265
5217
|
}
|
|
3266
|
-
function generateArtifactsFromSnapshot(
|
|
5218
|
+
function generateArtifactsFromSnapshot(snapshot, config) {
|
|
3267
5219
|
return throwBrowserUnsupported("generateArtifactsFromSnapshot");
|
|
3268
5220
|
}
|
|
3269
|
-
function resolveGeneratorProvider(
|
|
5221
|
+
function resolveGeneratorProvider(providerConfig, experimentalFlags) {
|
|
3270
5222
|
return throwBrowserUnsupported("resolveGeneratorProvider");
|
|
3271
5223
|
}
|
|
3272
|
-
async function runSchemaGenerator(
|
|
5224
|
+
async function runSchemaGenerator(options = {}) {
|
|
3273
5225
|
return throwBrowserUnsupported("runSchemaGenerator");
|
|
3274
5226
|
}
|
|
3275
5227
|
|
|
@@ -3284,10 +5236,12 @@ exports.DEFAULT_POSTGRES_SCHEMAS = DEFAULT_POSTGRES_SCHEMAS;
|
|
|
3284
5236
|
exports.assertInt = assertInt;
|
|
3285
5237
|
exports.coerceInt = coerceInt;
|
|
3286
5238
|
exports.createAuthClient = createAuthClient;
|
|
5239
|
+
exports.createAuthReactEmailInput = createAuthReactEmailInput;
|
|
3287
5240
|
exports.createClient = createClient;
|
|
3288
5241
|
exports.createModelFormAdapter = createModelFormAdapter;
|
|
3289
5242
|
exports.createPostgresIntrospectionProvider = createPostgresIntrospectionProvider;
|
|
3290
5243
|
exports.createTypedClient = createTypedClient;
|
|
5244
|
+
exports.defineAuthEmailTemplate = defineAuthEmailTemplate;
|
|
3291
5245
|
exports.defineDatabase = defineDatabase;
|
|
3292
5246
|
exports.defineGeneratorConfig = defineGeneratorConfig;
|
|
3293
5247
|
exports.defineModel = defineModel;
|
|
@@ -3300,9 +5254,11 @@ exports.isAthenaGatewayError = isAthenaGatewayError;
|
|
|
3300
5254
|
exports.isOk = isOk;
|
|
3301
5255
|
exports.loadGeneratorConfig = loadGeneratorConfig;
|
|
3302
5256
|
exports.normalizeAthenaError = normalizeAthenaError;
|
|
5257
|
+
exports.normalizeAthenaGatewayBaseUrl = normalizeAthenaGatewayBaseUrl;
|
|
3303
5258
|
exports.normalizeGeneratorConfig = normalizeGeneratorConfig;
|
|
3304
5259
|
exports.normalizeSchemaSelection = normalizeSchemaSelection;
|
|
3305
|
-
exports.parseBooleanFlag =
|
|
5260
|
+
exports.parseBooleanFlag = parseBooleanFlag2;
|
|
5261
|
+
exports.renderAthenaReactEmail = renderAthenaReactEmail;
|
|
3306
5262
|
exports.requireAffected = requireAffected;
|
|
3307
5263
|
exports.requireSuccess = requireSuccess;
|
|
3308
5264
|
exports.resolveGeneratorProvider = resolveGeneratorProvider;
|
|
@@ -3314,6 +5270,7 @@ exports.toModelPayload = toModelPayload;
|
|
|
3314
5270
|
exports.unwrap = unwrap;
|
|
3315
5271
|
exports.unwrapOne = unwrapOne;
|
|
3316
5272
|
exports.unwrapRows = unwrapRows;
|
|
5273
|
+
exports.verifyAthenaGatewayUrl = verifyAthenaGatewayUrl;
|
|
3317
5274
|
exports.withRetry = withRetry;
|
|
3318
5275
|
//# sourceMappingURL=browser.cjs.map
|
|
3319
5276
|
//# sourceMappingURL=browser.cjs.map
|