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