@xylex-group/athena 2.0.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +287 -95
  2. package/dist/browser.cjs +4791 -0
  3. package/dist/browser.cjs.map +1 -0
  4. package/dist/browser.d.cts +25 -0
  5. package/dist/browser.d.ts +25 -0
  6. package/dist/browser.js +4745 -0
  7. package/dist/browser.js.map +1 -0
  8. package/dist/cli/index.cjs +2087 -220
  9. package/dist/cli/index.cjs.map +1 -1
  10. package/dist/cli/index.d.cts +3 -2
  11. package/dist/cli/index.d.ts +3 -2
  12. package/dist/cli/index.js +2089 -222
  13. package/dist/cli/index.js.map +1 -1
  14. package/dist/cookies.cjs +890 -0
  15. package/dist/cookies.cjs.map +1 -0
  16. package/dist/cookies.d.cts +174 -0
  17. package/dist/cookies.d.ts +174 -0
  18. package/dist/cookies.js +869 -0
  19. package/dist/cookies.js.map +1 -0
  20. package/dist/index.cjs +3046 -1200
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +8 -408
  23. package/dist/index.d.ts +8 -408
  24. package/dist/index.js +3045 -1202
  25. package/dist/index.js.map +1 -1
  26. package/dist/{model-form-CVOtC8jq.d.ts → model-form-BpDXlbxb.d.ts} +97 -2
  27. package/dist/{model-form-hXkvHS_3.d.cts → model-form-hoE2jHIi.d.cts} +97 -2
  28. package/dist/pipeline-BNIw8pDQ.d.ts +8 -0
  29. package/dist/pipeline-DNIpEsN8.d.cts +8 -0
  30. package/dist/react-email-BvyCZnfW.d.cts +610 -0
  31. package/dist/react-email-qPA1wjFV.d.ts +610 -0
  32. package/dist/react.cjs +30 -9
  33. package/dist/react.cjs.map +1 -1
  34. package/dist/react.d.cts +4 -4
  35. package/dist/react.d.ts +4 -4
  36. package/dist/react.js +30 -9
  37. package/dist/react.js.map +1 -1
  38. package/dist/{types-BnzoaNRC.d.cts → types-A5e97acl.d.cts} +2 -1
  39. package/dist/{types-BnzoaNRC.d.ts → types-A5e97acl.d.ts} +2 -1
  40. package/dist/{pipeline-CQgV-Yfo.d.ts → types-BnD22-vb.d.ts} +2 -7
  41. package/dist/{pipeline-C-cN0ACi.d.cts → types-bDlr4u7p.d.cts} +2 -7
  42. package/dist/utils.cjs +153 -0
  43. package/dist/utils.cjs.map +1 -0
  44. package/dist/utils.d.cts +23 -0
  45. package/dist/utils.d.ts +23 -0
  46. package/dist/utils.js +146 -0
  47. package/dist/utils.js.map +1 -0
  48. package/package.json +87 -9
@@ -0,0 +1,4791 @@
1
+ 'use strict';
2
+
3
+ // src/gateway/errors.ts
4
+ var AthenaGatewayError = class _AthenaGatewayError extends Error {
5
+ code;
6
+ status;
7
+ endpoint;
8
+ method;
9
+ requestId;
10
+ hint;
11
+ causeDetail;
12
+ constructor(input) {
13
+ super(input.message);
14
+ this.name = "AthenaGatewayError";
15
+ this.code = input.code;
16
+ this.status = input.status ?? 0;
17
+ this.endpoint = input.endpoint;
18
+ this.method = input.method;
19
+ this.requestId = input.requestId;
20
+ this.hint = input.hint;
21
+ this.causeDetail = input.cause;
22
+ }
23
+ toDetails() {
24
+ return {
25
+ code: this.code,
26
+ message: this.message,
27
+ status: this.status,
28
+ endpoint: this.endpoint,
29
+ method: this.method,
30
+ requestId: this.requestId,
31
+ hint: this.hint,
32
+ cause: this.causeDetail
33
+ };
34
+ }
35
+ static fromResponse(response, fallback) {
36
+ const details = response.errorDetails;
37
+ if (details) {
38
+ return new _AthenaGatewayError({
39
+ code: details.code,
40
+ message: details.message,
41
+ status: details.status,
42
+ endpoint: details.endpoint ?? fallback.endpoint,
43
+ method: details.method ?? fallback.method,
44
+ requestId: details.requestId ?? fallback.requestId,
45
+ hint: details.hint,
46
+ cause: details.cause
47
+ });
48
+ }
49
+ return new _AthenaGatewayError({
50
+ code: "HTTP_ERROR",
51
+ message: response.error ?? "Gateway request failed",
52
+ status: response.status,
53
+ endpoint: fallback.endpoint,
54
+ method: fallback.method,
55
+ requestId: fallback.requestId
56
+ });
57
+ }
58
+ };
59
+ function isAthenaGatewayError(error) {
60
+ return error instanceof AthenaGatewayError;
61
+ }
62
+
63
+ // src/gateway/client.ts
64
+ var DEFAULT_BASE_URL = "https://athena-db.com";
65
+ var DEFAULT_CLIENT = "railway_direct";
66
+ var FALLBACK_SDK_VERSION = "1.3.0";
67
+ var SDK_NAME = "xylex-group/athena";
68
+ var SDK_VERSION = typeof process !== "undefined" && process?.env?.npm_package_version ? process.env.npm_package_version : FALLBACK_SDK_VERSION;
69
+ var SDK_HEADER_VALUE = `${SDK_NAME} ${SDK_VERSION}`;
70
+ function parseResponseBody(rawText, contentType) {
71
+ if (!rawText) {
72
+ return { parsed: null, parseFailed: false };
73
+ }
74
+ const contentTypeSuggestsJson = contentType?.toLowerCase().includes("application/json") ?? false;
75
+ const looksJson = contentTypeSuggestsJson || rawText.startsWith("{") || rawText.startsWith("[");
76
+ if (!looksJson) {
77
+ return { parsed: rawText, parseFailed: false };
78
+ }
79
+ try {
80
+ return { parsed: JSON.parse(rawText), parseFailed: false };
81
+ } catch {
82
+ return { parsed: rawText, parseFailed: true };
83
+ }
84
+ }
85
+ function normalizeHeaderValue(value) {
86
+ return value ? value : void 0;
87
+ }
88
+ function isRecord(value) {
89
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
90
+ }
91
+ function nonEmptyString(value) {
92
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
93
+ }
94
+ function resolveStructuredErrorPayload(payload) {
95
+ if (!isRecord(payload)) return null;
96
+ return isRecord(payload.error) ? payload.error : payload;
97
+ }
98
+ function resolveRequestId(headers) {
99
+ return headers.get("x-request-id") ?? headers.get("x-correlation-id") ?? headers.get("x-athena-request-id") ?? void 0;
100
+ }
101
+ function resolveErrorMessage(payload, fallback) {
102
+ const structuredPayload = resolveStructuredErrorPayload(payload);
103
+ if (structuredPayload) {
104
+ const messageCandidates = [structuredPayload.message, structuredPayload.error, structuredPayload.details];
105
+ for (const candidate of messageCandidates) {
106
+ const resolved = nonEmptyString(candidate);
107
+ if (resolved) return resolved;
108
+ }
109
+ }
110
+ const rawMessage = nonEmptyString(payload);
111
+ if (rawMessage) return rawMessage;
112
+ return fallback;
113
+ }
114
+ function resolveErrorHint(payload) {
115
+ const structuredPayload = resolveStructuredErrorPayload(payload);
116
+ return structuredPayload ? nonEmptyString(structuredPayload.hint) : void 0;
117
+ }
118
+ function resolveStatusText(response, payload) {
119
+ const rawStatusText = nonEmptyString(response.statusText);
120
+ if (rawStatusText) return rawStatusText;
121
+ const payloadRecord = isRecord(payload) ? payload : null;
122
+ return payloadRecord ? nonEmptyString(payloadRecord.statusText) ?? null : null;
123
+ }
124
+ function detailsFromError(error) {
125
+ return error.toDetails();
126
+ }
127
+ function toQueryScalar(value) {
128
+ if (value === null || value === void 0) return "null";
129
+ if (typeof value === "boolean") return value ? "true" : "false";
130
+ if (typeof value === "number") return Number.isFinite(value) ? String(value) : "null";
131
+ return String(value);
132
+ }
133
+ function toQueryArray(values) {
134
+ return `{${values.map(toQueryScalar).join(",")}}`;
135
+ }
136
+ function toRpcArgumentQueryValue(value) {
137
+ if (Array.isArray(value)) return toQueryArray(value);
138
+ if (value && typeof value === "object") return JSON.stringify(value);
139
+ return toQueryScalar(value);
140
+ }
141
+ function toRpcFilterQueryValue(filter) {
142
+ const value = filter.value;
143
+ switch (filter.operator) {
144
+ case "in": {
145
+ if (!Array.isArray(value)) {
146
+ throw new AthenaGatewayError({
147
+ code: "UNKNOWN_ERROR",
148
+ message: `RPC filter "${filter.column}" with operator "in" requires an array value`,
149
+ status: 0
150
+ });
151
+ }
152
+ return `in.${toQueryArray(value)}`;
153
+ }
154
+ case "is":
155
+ return `is.${toQueryScalar(value)}`;
156
+ case "eq":
157
+ case "neq":
158
+ case "gt":
159
+ case "gte":
160
+ case "lt":
161
+ case "lte":
162
+ case "like":
163
+ case "ilike":
164
+ return `${filter.operator}.${toQueryScalar(value)}`;
165
+ }
166
+ }
167
+ function buildRpcGetEndpoint(payload) {
168
+ const functionName = (payload.function_name ?? payload.function).trim();
169
+ if (!functionName) {
170
+ throw new AthenaGatewayError({
171
+ code: "UNKNOWN_ERROR",
172
+ message: "rpc requires a function name",
173
+ status: 0,
174
+ endpoint: "/gateway/rpc",
175
+ method: "GET"
176
+ });
177
+ }
178
+ const query = new URLSearchParams();
179
+ if (payload.schema) query.set("schema", payload.schema);
180
+ if (payload.select) query.set("select", payload.select);
181
+ if (payload.count) query.set("count", payload.count);
182
+ if (payload.head) query.set("head", "true");
183
+ if (typeof payload.limit === "number") query.set("limit", String(payload.limit));
184
+ if (typeof payload.offset === "number") query.set("offset", String(payload.offset));
185
+ if (payload.order?.column) {
186
+ query.set(
187
+ "order",
188
+ payload.order.ascending === false ? `${payload.order.column}.desc` : payload.order.column
189
+ );
190
+ }
191
+ if (payload.args) {
192
+ for (const [key, value] of Object.entries(payload.args)) {
193
+ query.set(key, toRpcArgumentQueryValue(value));
194
+ }
195
+ }
196
+ if (payload.filters?.length) {
197
+ for (const filter of payload.filters) {
198
+ if (payload.args && Object.prototype.hasOwnProperty.call(payload.args, filter.column)) {
199
+ throw new AthenaGatewayError({
200
+ code: "UNKNOWN_ERROR",
201
+ message: `RPC filter "${filter.column}" conflicts with RPC argument "${filter.column}" in GET mode`,
202
+ status: 0
203
+ });
204
+ }
205
+ query.set(filter.column, toRpcFilterQueryValue(filter));
206
+ }
207
+ }
208
+ const endpoint = `/rpc/${encodeURIComponent(functionName)}`;
209
+ const queryText = query.toString();
210
+ const withQuery = queryText ? `${endpoint}?${queryText}` : endpoint;
211
+ return withQuery;
212
+ }
213
+ function buildHeaders(config, options) {
214
+ const mergedStripNulls = options?.stripNulls ?? true;
215
+ const extraHeaders = {
216
+ ...config.headers ?? {},
217
+ ...options?.headers ?? {}
218
+ };
219
+ const headerClient = extraHeaders["x-athena-client"] ?? extraHeaders["X-Athena-Client"];
220
+ const finalClient = options?.client ?? config.client ?? (typeof headerClient === "string" ? headerClient : void 0) ?? DEFAULT_CLIENT;
221
+ const finalApiKey = options?.apiKey ?? config.apiKey;
222
+ const finalPublishEvent = options?.publishEvent ?? config.publishEvent;
223
+ const headers = {
224
+ "Content-Type": "application/json",
225
+ "X-Athena-Sdk": SDK_HEADER_VALUE
226
+ };
227
+ if (options?.userId ?? config.userId) {
228
+ headers["X-User-Id"] = options?.userId ?? config.userId ?? "";
229
+ }
230
+ if (options?.organizationId ?? config.organizationId) {
231
+ headers["X-Organization-Id"] = options?.organizationId ?? config.organizationId ?? "";
232
+ }
233
+ if (finalClient) {
234
+ headers["X-Athena-Client"] = finalClient;
235
+ }
236
+ const finalBackend = options?.backend ?? config.backend;
237
+ if (finalBackend) {
238
+ const type = typeof finalBackend === "string" ? finalBackend : finalBackend.type;
239
+ if (type) headers["X-Backend-Type"] = type;
240
+ }
241
+ if (typeof mergedStripNulls === "boolean") {
242
+ headers["X-Strip-Nulls"] = mergedStripNulls ? "true" : "false";
243
+ }
244
+ if (finalPublishEvent) {
245
+ headers["X-Publish-Event"] = finalPublishEvent;
246
+ }
247
+ if (finalApiKey) {
248
+ headers["apikey"] = finalApiKey;
249
+ headers["x-api-key"] = headers["x-api-key"] ?? finalApiKey;
250
+ }
251
+ const athenaClientKeys = ["x-athena-client", "X-Athena-Client"];
252
+ Object.entries(extraHeaders).forEach(([key, value]) => {
253
+ if (athenaClientKeys.includes(key)) return;
254
+ const normalized = normalizeHeaderValue(value);
255
+ if (normalized) {
256
+ headers[key] = normalized;
257
+ }
258
+ });
259
+ return headers;
260
+ }
261
+ async function callAthena(config, endpoint, method, payload, options) {
262
+ const baseUrl = (options?.baseUrl ?? config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
263
+ const url = `${baseUrl}${endpoint}`;
264
+ const headers = buildHeaders(config, options);
265
+ try {
266
+ const requestInit = {
267
+ method,
268
+ headers
269
+ };
270
+ if (method !== "GET") {
271
+ requestInit.body = JSON.stringify(payload);
272
+ }
273
+ const response = await fetch(url, requestInit);
274
+ const rawText = await response.text();
275
+ const requestId = resolveRequestId(response.headers);
276
+ const parsedBody = parseResponseBody(
277
+ rawText ?? "",
278
+ response.headers.get("content-type")
279
+ );
280
+ if (parsedBody.parseFailed) {
281
+ const invalidJsonError = new AthenaGatewayError({
282
+ code: "INVALID_JSON",
283
+ message: "Gateway returned malformed JSON",
284
+ status: response.status,
285
+ endpoint,
286
+ method,
287
+ requestId,
288
+ hint: "Verify the gateway response body is valid JSON.",
289
+ cause: rawText.slice(0, 300)
290
+ });
291
+ return {
292
+ ok: false,
293
+ status: response.status,
294
+ statusText: resolveStatusText(response, parsedBody.parsed),
295
+ data: null,
296
+ error: invalidJsonError.message,
297
+ errorDetails: detailsFromError(invalidJsonError),
298
+ raw: parsedBody.parsed
299
+ };
300
+ }
301
+ const parsed = parsedBody.parsed;
302
+ const parsedPayload = isRecord(parsed) ? parsed : null;
303
+ if (!response.ok) {
304
+ const httpError = new AthenaGatewayError({
305
+ code: "HTTP_ERROR",
306
+ message: resolveErrorMessage(
307
+ parsed,
308
+ `Athena gateway ${method} ${endpoint} failed with status ${response.status}`
309
+ ),
310
+ status: response.status,
311
+ endpoint,
312
+ method,
313
+ requestId,
314
+ hint: resolveErrorHint(parsed)
315
+ });
316
+ return {
317
+ ok: false,
318
+ status: response.status,
319
+ statusText: resolveStatusText(response, parsed),
320
+ data: null,
321
+ error: httpError.message,
322
+ errorDetails: detailsFromError(httpError),
323
+ raw: parsed
324
+ };
325
+ }
326
+ const payloadData = parsedPayload && "data" in parsedPayload ? parsedPayload.data : parsed;
327
+ const payloadCount = parsedPayload && "count" in parsedPayload ? typeof parsedPayload.count === "number" || parsedPayload.count === null ? parsedPayload.count : void 0 : void 0;
328
+ return {
329
+ ok: true,
330
+ status: response.status,
331
+ statusText: resolveStatusText(response, parsed),
332
+ data: payloadData ?? null,
333
+ count: payloadCount,
334
+ error: void 0,
335
+ errorDetails: null,
336
+ raw: parsed
337
+ };
338
+ } catch (callError) {
339
+ const message = callError instanceof Error ? callError.message : String(callError);
340
+ const networkError = new AthenaGatewayError({
341
+ code: "NETWORK_ERROR",
342
+ message: `Network error while calling ${method} ${endpoint}: ${message}`,
343
+ endpoint,
344
+ method,
345
+ cause: message,
346
+ hint: "Check gateway URL, DNS, and network reachability."
347
+ });
348
+ return {
349
+ ok: false,
350
+ status: 0,
351
+ statusText: null,
352
+ data: null,
353
+ error: networkError.message,
354
+ errorDetails: detailsFromError(networkError),
355
+ raw: null
356
+ };
357
+ }
358
+ }
359
+ function createAthenaGatewayClient(config = {}) {
360
+ return {
361
+ baseUrl: (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, ""),
362
+ buildHeaders(options) {
363
+ return buildHeaders(config, options);
364
+ },
365
+ fetchGateway(payload, options) {
366
+ return callAthena(config, "/gateway/fetch", "POST", payload, options);
367
+ },
368
+ insertGateway(payload, options) {
369
+ return callAthena(config, "/gateway/insert", "PUT", payload, options);
370
+ },
371
+ updateGateway(payload, options) {
372
+ return callAthena(config, "/gateway/update", "POST", payload, options);
373
+ },
374
+ deleteGateway(payload, options) {
375
+ return callAthena(config, "/gateway/delete", "DELETE", payload, options);
376
+ },
377
+ rpcGateway(payload, options) {
378
+ if (options?.get) {
379
+ const endpoint = buildRpcGetEndpoint(payload);
380
+ return callAthena(config, endpoint, "GET", null, options);
381
+ }
382
+ return callAthena(config, "/gateway/rpc", "POST", payload, options);
383
+ },
384
+ queryGateway(payload, options) {
385
+ return callAthena(config, "/gateway/query", "POST", payload, options);
386
+ }
387
+ };
388
+ }
389
+
390
+ // src/sql-identifiers.ts
391
+ var SIMPLE_IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
392
+ var COMPOSITE_IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/;
393
+ var SQL_ALIAS_PATTERN = /^([A-Za-z_][A-Za-z0-9_.]*)\s+(?:as\s+)?([A-Za-z_][A-Za-z0-9_]*)$/i;
394
+ var RESPONSE_ALIAS_PATTERN = /^([A-Za-z_][A-Za-z0-9_]*)\s*:\s*([A-Za-z_][A-Za-z0-9_.]*)$/i;
395
+ function quoteIdentifierSegment(identifier2) {
396
+ return `"${identifier2.replace(/"/g, '""')}"`;
397
+ }
398
+ function parseAliasedIdentifierToken(token) {
399
+ const responseAliasMatch = RESPONSE_ALIAS_PATTERN.exec(token);
400
+ if (responseAliasMatch) {
401
+ const [, aliasIdentifier2, baseIdentifier2] = responseAliasMatch;
402
+ if (COMPOSITE_IDENTIFIER_PATTERN.test(baseIdentifier2) && SIMPLE_IDENTIFIER_PATTERN.test(aliasIdentifier2)) {
403
+ return { baseIdentifier: baseIdentifier2, aliasIdentifier: aliasIdentifier2 };
404
+ }
405
+ }
406
+ const sqlAliasMatch = SQL_ALIAS_PATTERN.exec(token);
407
+ if (!sqlAliasMatch) {
408
+ return null;
409
+ }
410
+ const [, baseIdentifier, aliasIdentifier] = sqlAliasMatch;
411
+ if (!COMPOSITE_IDENTIFIER_PATTERN.test(baseIdentifier) || !SIMPLE_IDENTIFIER_PATTERN.test(aliasIdentifier)) {
412
+ return null;
413
+ }
414
+ return { baseIdentifier, aliasIdentifier };
415
+ }
416
+ function quoteQualifiedIdentifier(identifier2) {
417
+ return identifier2.split(".").map((segment) => quoteIdentifierSegment(segment)).join(".");
418
+ }
419
+ function quoteSelectToken(token) {
420
+ if (token === "*") return token;
421
+ if (COMPOSITE_IDENTIFIER_PATTERN.test(token)) {
422
+ return quoteQualifiedIdentifier(token);
423
+ }
424
+ const aliasedIdentifier = parseAliasedIdentifierToken(token);
425
+ if (!aliasedIdentifier) {
426
+ return token;
427
+ }
428
+ const { baseIdentifier, aliasIdentifier } = aliasedIdentifier;
429
+ return `${quoteQualifiedIdentifier(baseIdentifier)} AS ${quoteIdentifierSegment(aliasIdentifier)}`;
430
+ }
431
+ function quoteSelectColumnToken(token) {
432
+ const trimmed = token.trim();
433
+ if (!trimmed || trimmed === "*") return trimmed || "*";
434
+ const responseAliasMatch = RESPONSE_ALIAS_PATTERN.exec(trimmed);
435
+ if (responseAliasMatch) {
436
+ const [, aliasIdentifier, baseIdentifier] = responseAliasMatch;
437
+ return `${quoteQualifiedIdentifier(baseIdentifier)} AS ${quoteIdentifierSegment(aliasIdentifier)}`;
438
+ }
439
+ return quoteQualifiedIdentifier(trimmed);
440
+ }
441
+ function canAutoQuoteToken(token) {
442
+ if (token === "*") return true;
443
+ if (COMPOSITE_IDENTIFIER_PATTERN.test(token)) return true;
444
+ return parseAliasedIdentifierToken(token) != null;
445
+ }
446
+ function splitTopLevelCommaSeparated(input) {
447
+ const parts = [];
448
+ let buffer = "";
449
+ let singleQuoted = false;
450
+ let doubleQuoted = false;
451
+ let depth = 0;
452
+ for (let index = 0; index < input.length; index += 1) {
453
+ const char = input[index];
454
+ const next = index + 1 < input.length ? input[index + 1] : "";
455
+ if (singleQuoted) {
456
+ buffer += char;
457
+ if (char === "'" && next === "'") {
458
+ buffer += next;
459
+ index += 1;
460
+ continue;
461
+ }
462
+ if (char === "'") {
463
+ singleQuoted = false;
464
+ }
465
+ continue;
466
+ }
467
+ if (doubleQuoted) {
468
+ buffer += char;
469
+ if (char === '"' && next === '"') {
470
+ buffer += next;
471
+ index += 1;
472
+ continue;
473
+ }
474
+ if (char === '"') {
475
+ doubleQuoted = false;
476
+ }
477
+ continue;
478
+ }
479
+ if (char === "'") {
480
+ singleQuoted = true;
481
+ buffer += char;
482
+ continue;
483
+ }
484
+ if (char === '"') {
485
+ doubleQuoted = true;
486
+ buffer += char;
487
+ continue;
488
+ }
489
+ if (char === "(") {
490
+ depth += 1;
491
+ buffer += char;
492
+ continue;
493
+ }
494
+ if (char === ")") {
495
+ depth -= 1;
496
+ if (depth < 0) return null;
497
+ buffer += char;
498
+ continue;
499
+ }
500
+ if (char === "," && depth === 0) {
501
+ parts.push(buffer.trim());
502
+ buffer = "";
503
+ continue;
504
+ }
505
+ buffer += char;
506
+ }
507
+ if (singleQuoted || doubleQuoted || depth !== 0) {
508
+ return null;
509
+ }
510
+ if (buffer.trim().length > 0) {
511
+ parts.push(buffer.trim());
512
+ }
513
+ return parts;
514
+ }
515
+ function quoteSelectColumnsExpression(columns) {
516
+ const trimmed = columns.trim();
517
+ if (!trimmed || trimmed === "*") return trimmed || "*";
518
+ const tokens = splitTopLevelCommaSeparated(trimmed);
519
+ if (!tokens || tokens.length === 0) {
520
+ return trimmed;
521
+ }
522
+ if (!tokens.every(canAutoQuoteToken)) {
523
+ return trimmed;
524
+ }
525
+ return tokens.map(quoteSelectToken).join(", ");
526
+ }
527
+ var SqlIdentifierPath = class {
528
+ segments;
529
+ constructor(segments) {
530
+ this.segments = segments;
531
+ }
532
+ toSql() {
533
+ return this.segments.map(quoteIdentifierSegment).join(".");
534
+ }
535
+ toString() {
536
+ return this.toSql();
537
+ }
538
+ };
539
+ function identifier(...segments) {
540
+ const expandedSegments = segments.flatMap((segment) => segment.split(".")).map((segment) => segment.trim()).filter((segment) => segment.length > 0);
541
+ return new SqlIdentifierPath(expandedSegments);
542
+ }
543
+
544
+ // src/auth/react-email.ts
545
+ var reactEmailRenderModulePromise;
546
+ function isRecord2(value) {
547
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
548
+ }
549
+ function isFunction(value) {
550
+ return typeof value === "function";
551
+ }
552
+ function toStringOrUndefined(value) {
553
+ if (typeof value !== "string") return void 0;
554
+ return value;
555
+ }
556
+ function nowIsoString() {
557
+ return (/* @__PURE__ */ new Date()).toISOString();
558
+ }
559
+ function emitReactEmailEvent(observe, phase, input = {}) {
560
+ if (!observe) return;
561
+ try {
562
+ observe({
563
+ phase,
564
+ timestamp: nowIsoString(),
565
+ ...input
566
+ });
567
+ } catch {
568
+ }
569
+ }
570
+ function mergeRenderDefaults(input, defaults) {
571
+ return {
572
+ ...input,
573
+ pretty: input.pretty ?? defaults?.pretty,
574
+ includePlainText: input.includePlainText ?? defaults?.includePlainText
575
+ };
576
+ }
577
+ function mergeRuntimeOptions(options) {
578
+ if (!options) return void 0;
579
+ return {
580
+ defaults: options.defaults,
581
+ observe: options.observe,
582
+ route: "route" in options ? options.route : void 0
583
+ };
584
+ }
585
+ async function resolveReactEmailRenderModule() {
586
+ if (!reactEmailRenderModulePromise) {
587
+ reactEmailRenderModulePromise = (async () => {
588
+ try {
589
+ const loaded = await import('@react-email/render');
590
+ if (!isFunction(loaded.render)) {
591
+ throw new Error("missing render(...) export");
592
+ }
593
+ return {
594
+ render: loaded.render,
595
+ toPlainText: isFunction(loaded.toPlainText) ? loaded.toPlainText : void 0,
596
+ pretty: isFunction(loaded.pretty) ? loaded.pretty : void 0
597
+ };
598
+ } catch (error) {
599
+ const message = error instanceof Error ? error.message : String(error);
600
+ throw new Error(
601
+ `React Email rendering requires @react-email/render. Install it in your project (for example: pnpm add @react-email/render). Loader error: ${message}`
602
+ );
603
+ }
604
+ })();
605
+ }
606
+ if (!reactEmailRenderModulePromise) {
607
+ throw new Error("React Email renderer module failed to initialize");
608
+ }
609
+ return reactEmailRenderModulePromise;
610
+ }
611
+ async function resolveReactEmailElement(input) {
612
+ if (input.element != null) {
613
+ return input.element;
614
+ }
615
+ if (!input.component) {
616
+ throw new Error("react email payload requires either `element` or `component`");
617
+ }
618
+ try {
619
+ const reactModule = await import('react');
620
+ if (typeof reactModule.createElement !== "function") {
621
+ throw new Error("react createElement(...) export is unavailable");
622
+ }
623
+ return reactModule.createElement(
624
+ input.component,
625
+ input.props ?? {}
626
+ );
627
+ } catch (error) {
628
+ const message = error instanceof Error ? error.message : String(error);
629
+ throw new Error(
630
+ `React Email component rendering requires react runtime support. Install react in your project. Loader error: ${message}`
631
+ );
632
+ }
633
+ }
634
+ function createAuthReactEmailInput(component, props, overrides = {}) {
635
+ return {
636
+ ...overrides,
637
+ component,
638
+ props
639
+ };
640
+ }
641
+ function defineAuthEmailTemplate(definition) {
642
+ const react = (props, overrides) => createAuthReactEmailInput(definition.component, props, {
643
+ ...definition.defaults,
644
+ ...overrides
645
+ });
646
+ return {
647
+ component: definition.component,
648
+ react,
649
+ toTemplateCreate: (input) => {
650
+ const templateKey = input.templateKey ?? definition.templateKey;
651
+ const subjectTemplate = input.subjectTemplate ?? definition.subjectTemplate;
652
+ if (!templateKey) {
653
+ throw new Error("defineAuthEmailTemplate.toTemplateCreate requires templateKey");
654
+ }
655
+ if (!subjectTemplate) {
656
+ throw new Error("defineAuthEmailTemplate.toTemplateCreate requires subjectTemplate");
657
+ }
658
+ const { props, react: reactOverrides, ...rest } = input;
659
+ return {
660
+ ...rest,
661
+ templateKey,
662
+ subjectTemplate,
663
+ react: react(props, reactOverrides)
664
+ };
665
+ },
666
+ toTemplateUpdate: (input) => {
667
+ const { props, react: reactOverrides, ...rest } = input;
668
+ return {
669
+ ...rest,
670
+ react: react(props, reactOverrides)
671
+ };
672
+ }
673
+ };
674
+ }
675
+ async function renderAthenaReactEmail(input, options) {
676
+ if (!isRecord2(input)) {
677
+ throw new Error("react email payload must be an object");
678
+ }
679
+ const runtimeOptions = mergeRuntimeOptions(options);
680
+ const start = Date.now();
681
+ emitReactEmailEvent(runtimeOptions?.observe, "render:start", {
682
+ route: runtimeOptions?.route,
683
+ message: "Rendering react email payload"
684
+ });
685
+ try {
686
+ const normalizedInput = mergeRenderDefaults(input, runtimeOptions?.defaults);
687
+ const element = await resolveReactEmailElement(normalizedInput);
688
+ const renderModule = await resolveReactEmailRenderModule();
689
+ const htmlValue = await renderModule.render(element);
690
+ const renderedHtml = typeof htmlValue === "string" ? htmlValue : String(htmlValue ?? "");
691
+ if (!renderedHtml.trim()) {
692
+ throw new Error("react email renderer returned an empty HTML string");
693
+ }
694
+ let html = renderedHtml;
695
+ if (normalizedInput.pretty && renderModule.pretty) {
696
+ const prettyValue = await renderModule.pretty(renderedHtml);
697
+ if (typeof prettyValue === "string" && prettyValue.trim().length > 0) {
698
+ html = prettyValue;
699
+ }
700
+ }
701
+ const explicitText = toStringOrUndefined(normalizedInput.text);
702
+ if (explicitText !== void 0) {
703
+ emitReactEmailEvent(runtimeOptions?.observe, "render:success", {
704
+ route: runtimeOptions?.route,
705
+ durationMs: Date.now() - start,
706
+ message: "Rendered react email with explicit text"
707
+ });
708
+ return {
709
+ html,
710
+ text: explicitText
711
+ };
712
+ }
713
+ if (normalizedInput.includePlainText === false || !renderModule.toPlainText) {
714
+ emitReactEmailEvent(runtimeOptions?.observe, "render:success", {
715
+ route: runtimeOptions?.route,
716
+ durationMs: Date.now() - start,
717
+ message: "Rendered react email without plain-text derivation"
718
+ });
719
+ return { html };
720
+ }
721
+ const plainTextValue = await renderModule.toPlainText(html);
722
+ const plainText = toStringOrUndefined(plainTextValue);
723
+ emitReactEmailEvent(runtimeOptions?.observe, "render:success", {
724
+ route: runtimeOptions?.route,
725
+ durationMs: Date.now() - start,
726
+ message: plainText ? "Rendered react email with derived plain text" : "Rendered react email HTML only"
727
+ });
728
+ if (plainText === void 0) {
729
+ return { html };
730
+ }
731
+ return {
732
+ html,
733
+ text: plainText
734
+ };
735
+ } catch (error) {
736
+ const message = error instanceof Error ? error.message : String(error);
737
+ emitReactEmailEvent(runtimeOptions?.observe, "render:error", {
738
+ route: runtimeOptions?.route,
739
+ durationMs: Date.now() - start,
740
+ error: message,
741
+ message: "Failed to render react email payload"
742
+ });
743
+ throw error;
744
+ }
745
+ }
746
+ async function resolveReactEmailPayloadFields(input, fields, options) {
747
+ const { react, ...payloadWithoutReact } = input;
748
+ if (!react) {
749
+ return payloadWithoutReact;
750
+ }
751
+ const rendered = await renderAthenaReactEmail(react, options);
752
+ const payload = {
753
+ ...payloadWithoutReact
754
+ };
755
+ payload[fields.htmlField] = rendered.html;
756
+ const currentTextValue = payload[fields.textField];
757
+ if (rendered.text !== void 0 && (currentTextValue === void 0 || currentTextValue === null || currentTextValue === "")) {
758
+ payload[fields.textField] = rendered.text;
759
+ }
760
+ if (fields.variablesField && (payload[fields.variablesField] === void 0 || payload[fields.variablesField] === null) && isRecord2(react.props)) {
761
+ const derivedVariables = Object.keys(react.props);
762
+ if (derivedVariables.length > 0) {
763
+ payload[fields.variablesField] = derivedVariables;
764
+ }
765
+ }
766
+ return payload;
767
+ }
768
+
769
+ // src/auth/client.ts
770
+ var DEFAULT_AUTH_BASE_URL = "http://localhost:3001/api/auth";
771
+ var FALLBACK_SDK_VERSION2 = "1.0.0";
772
+ var SDK_NAME2 = "xylex-group/athena-auth";
773
+ var SDK_VERSION2 = typeof process !== "undefined" && process?.env?.npm_package_version ? process.env.npm_package_version : FALLBACK_SDK_VERSION2;
774
+ var SDK_HEADER_VALUE2 = `${SDK_NAME2} ${SDK_VERSION2}`;
775
+ function normalizeBaseUrl(baseUrl) {
776
+ return (baseUrl ?? DEFAULT_AUTH_BASE_URL).replace(/\/$/, "");
777
+ }
778
+ function isRecord3(value) {
779
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
780
+ }
781
+ function normalizeHeaderValue2(value) {
782
+ return value ? value : void 0;
783
+ }
784
+ function parseResponseBody2(rawText, contentType) {
785
+ if (!rawText) {
786
+ return { parsed: null, parseFailed: false };
787
+ }
788
+ const contentTypeSuggestsJson = contentType?.toLowerCase().includes("application/json") ?? false;
789
+ const looksJson = contentTypeSuggestsJson || rawText.startsWith("{") || rawText.startsWith("[");
790
+ if (!looksJson) {
791
+ return { parsed: rawText, parseFailed: false };
792
+ }
793
+ try {
794
+ return { parsed: JSON.parse(rawText), parseFailed: false };
795
+ } catch {
796
+ return { parsed: rawText, parseFailed: true };
797
+ }
798
+ }
799
+ function resolveRequestId2(headers) {
800
+ return headers.get("x-request-id") ?? headers.get("x-correlation-id") ?? headers.get("x-athena-request-id") ?? void 0;
801
+ }
802
+ function resolveErrorMessage2(payload, fallback) {
803
+ if (isRecord3(payload)) {
804
+ const messageCandidates = [payload.error, payload.message, payload.details];
805
+ for (const candidate of messageCandidates) {
806
+ if (typeof candidate === "string" && candidate.trim().length > 0) {
807
+ return candidate.trim();
808
+ }
809
+ }
810
+ }
811
+ if (typeof payload === "string" && payload.trim().length > 0) {
812
+ return payload.trim();
813
+ }
814
+ return fallback;
815
+ }
816
+ function toErrorDetails(input) {
817
+ return {
818
+ code: input.code,
819
+ message: input.message,
820
+ status: input.status,
821
+ endpoint: input.endpoint,
822
+ method: input.method,
823
+ requestId: input.requestId,
824
+ hint: input.hint,
825
+ cause: input.cause
826
+ };
827
+ }
828
+ function mergeCallOptions(base, override) {
829
+ if (!base && !override) return void 0;
830
+ return {
831
+ ...base,
832
+ ...override,
833
+ headers: {
834
+ ...base?.headers ?? {},
835
+ ...override?.headers ?? {}
836
+ }
837
+ };
838
+ }
839
+ function extractFetchOptions(input) {
840
+ if (!input) {
841
+ return {
842
+ payload: void 0,
843
+ fetchOptions: void 0
844
+ };
845
+ }
846
+ const { fetchOptions, ...rest } = input;
847
+ const hasPayloadKeys = Object.keys(rest).length > 0;
848
+ return {
849
+ payload: hasPayloadKeys ? rest : void 0,
850
+ fetchOptions
851
+ };
852
+ }
853
+ function buildHeaders2(config, options) {
854
+ const headers = {
855
+ "Content-Type": "application/json",
856
+ "X-Athena-Sdk": SDK_HEADER_VALUE2
857
+ };
858
+ const apiKey = options?.apiKey ?? config.apiKey;
859
+ if (apiKey) {
860
+ headers.apikey = apiKey;
861
+ headers["x-api-key"] = apiKey;
862
+ }
863
+ const bearerToken = options?.bearerToken ?? config.bearerToken;
864
+ if (bearerToken) {
865
+ headers.Authorization = `Bearer ${bearerToken}`;
866
+ }
867
+ const mergedExtraHeaders = {
868
+ ...config.headers ?? {},
869
+ ...options?.headers ?? {}
870
+ };
871
+ Object.entries(mergedExtraHeaders).forEach(([key, value]) => {
872
+ const normalized = normalizeHeaderValue2(value);
873
+ if (normalized) {
874
+ headers[key] = normalized;
875
+ }
876
+ });
877
+ return headers;
878
+ }
879
+ function appendQueryParam(searchParams, key, value) {
880
+ if (value === void 0 || value === null) return;
881
+ if (Array.isArray(value)) {
882
+ value.forEach((item) => {
883
+ searchParams.append(key, String(item));
884
+ });
885
+ return;
886
+ }
887
+ searchParams.append(key, String(value));
888
+ }
889
+ function buildRequestUrl(baseUrl, endpoint, query) {
890
+ const url = `${baseUrl}${endpoint}`;
891
+ if (!query || Object.keys(query).length === 0) return url;
892
+ const searchParams = new URLSearchParams();
893
+ Object.entries(query).forEach(([key, value]) => appendQueryParam(searchParams, key, value));
894
+ const queryText = searchParams.toString();
895
+ return queryText ? `${url}?${queryText}` : url;
896
+ }
897
+ function inferDefaultMethod(endpoint) {
898
+ if (endpoint.startsWith("/reset-password/")) {
899
+ return "GET";
900
+ }
901
+ switch (endpoint) {
902
+ case "/get-session":
903
+ case "/list-sessions":
904
+ case "/verify-email":
905
+ case "/change-email/verify":
906
+ case "/delete-user/verify":
907
+ case "/email-list":
908
+ case "/email/list":
909
+ case "/delete-user/callback":
910
+ case "/list-accounts":
911
+ case "/passkey/generate-register-options":
912
+ case "/passkey/list-user-passkeys":
913
+ case "/.well-known/webauthn":
914
+ case "/admin/list-users":
915
+ case "/admin/athena-client/list":
916
+ case "/admin/audit-log/list":
917
+ case "/admin/email/get":
918
+ case "/admin/email-failure/list":
919
+ case "/admin/email-failure/get":
920
+ case "/admin/email-template/get":
921
+ case "/admin/email-template/list":
922
+ case "/admin/email/list":
923
+ case "/api-key/get":
924
+ case "/api-key/list":
925
+ case "/organization/get-full-organization":
926
+ case "/organization/list":
927
+ case "/organization/get-invitation":
928
+ case "/organization/list-invitations":
929
+ case "/organization/list-user-invitations":
930
+ case "/organization/list-members":
931
+ case "/organization/get-active-member":
932
+ case "/health":
933
+ case "/ok":
934
+ case "/error":
935
+ return "GET";
936
+ default:
937
+ return "POST";
938
+ }
939
+ }
940
+ async function callAuthEndpoint(config, context, body, query, options) {
941
+ const baseUrl = normalizeBaseUrl(options?.baseUrl ?? config.baseUrl);
942
+ const url = buildRequestUrl(baseUrl, context.endpoint, query);
943
+ const headers = buildHeaders2(config, options);
944
+ const credentials = options?.credentials ?? config.credentials ?? "include";
945
+ const requestInit = {
946
+ method: context.method,
947
+ headers,
948
+ credentials,
949
+ signal: options?.signal
950
+ };
951
+ if (context.method !== "GET") {
952
+ requestInit.body = JSON.stringify(body ?? {});
953
+ }
954
+ const fetcher = config.fetch ?? globalThis.fetch;
955
+ if (!fetcher) {
956
+ const details = toErrorDetails({
957
+ code: "UNKNOWN_ERROR",
958
+ message: "No fetch implementation available for auth client",
959
+ status: 0,
960
+ endpoint: context.endpoint,
961
+ method: context.method,
962
+ hint: "Use Node 18+ or provide `fetch` via createClient(..., { auth: { fetch } }) or createAuthClient({ fetch })"
963
+ });
964
+ return {
965
+ ok: false,
966
+ status: 0,
967
+ data: null,
968
+ error: details.message,
969
+ errorDetails: details,
970
+ raw: null
971
+ };
972
+ }
973
+ try {
974
+ const response = await fetcher(url, requestInit);
975
+ const rawText = await response.text();
976
+ const requestId = resolveRequestId2(response.headers);
977
+ const parsedBody = parseResponseBody2(rawText ?? "", response.headers.get("content-type"));
978
+ if (parsedBody.parseFailed) {
979
+ const details = toErrorDetails({
980
+ code: "INVALID_JSON",
981
+ message: "Auth server returned malformed JSON",
982
+ status: response.status,
983
+ endpoint: context.endpoint,
984
+ method: context.method,
985
+ requestId,
986
+ hint: "Verify the auth endpoint response body is valid JSON.",
987
+ cause: rawText.slice(0, 300)
988
+ });
989
+ return {
990
+ ok: false,
991
+ status: response.status,
992
+ data: null,
993
+ error: details.message,
994
+ errorDetails: details,
995
+ raw: parsedBody.parsed
996
+ };
997
+ }
998
+ const parsed = parsedBody.parsed;
999
+ if (!response.ok) {
1000
+ const details = toErrorDetails({
1001
+ code: "HTTP_ERROR",
1002
+ message: resolveErrorMessage2(
1003
+ parsed,
1004
+ `Auth endpoint ${context.method} ${context.endpoint} failed with status ${response.status}`
1005
+ ),
1006
+ status: response.status,
1007
+ endpoint: context.endpoint,
1008
+ method: context.method,
1009
+ requestId
1010
+ });
1011
+ return {
1012
+ ok: false,
1013
+ status: response.status,
1014
+ data: null,
1015
+ error: details.message,
1016
+ errorDetails: details,
1017
+ raw: parsed
1018
+ };
1019
+ }
1020
+ return {
1021
+ ok: true,
1022
+ status: response.status,
1023
+ data: parsed ?? null,
1024
+ error: null,
1025
+ errorDetails: null,
1026
+ raw: parsed
1027
+ };
1028
+ } catch (callError) {
1029
+ const message = callError instanceof Error ? callError.message : String(callError);
1030
+ const details = toErrorDetails({
1031
+ code: "NETWORK_ERROR",
1032
+ message: `Network error while calling ${context.method} ${context.endpoint}: ${message}`,
1033
+ status: 0,
1034
+ endpoint: context.endpoint,
1035
+ method: context.method,
1036
+ cause: message,
1037
+ hint: "Check auth server URL, DNS, and network reachability."
1038
+ });
1039
+ return {
1040
+ ok: false,
1041
+ status: 0,
1042
+ data: null,
1043
+ error: details.message,
1044
+ errorDetails: details,
1045
+ raw: null
1046
+ };
1047
+ }
1048
+ }
1049
+ function executePostWithCompatibleInput(config, context, input, options) {
1050
+ const { payload, fetchOptions } = extractFetchOptions(input);
1051
+ const mergedOptions = mergeCallOptions(fetchOptions, options);
1052
+ return callAuthEndpoint(config, context, payload ?? {}, void 0, mergedOptions);
1053
+ }
1054
+ function executePostWithOptionalInput(config, context, input, options) {
1055
+ const { fetchOptions } = extractFetchOptions(input);
1056
+ const mergedOptions = mergeCallOptions(fetchOptions, options);
1057
+ return callAuthEndpoint(config, context, {}, void 0, mergedOptions);
1058
+ }
1059
+ function executeGetWithCompatibleInput(config, context, input, options) {
1060
+ const { fetchOptions } = extractFetchOptions(input);
1061
+ const mergedOptions = mergeCallOptions(fetchOptions, options);
1062
+ return callAuthEndpoint(config, context, void 0, void 0, mergedOptions);
1063
+ }
1064
+ function executeGetWithQueryCompatibleInput(config, context, input, options) {
1065
+ const { payload, fetchOptions } = extractFetchOptions(input);
1066
+ const mergedOptions = mergeCallOptions(fetchOptions, options);
1067
+ const query = payload?.query;
1068
+ return callAuthEndpoint(
1069
+ config,
1070
+ context,
1071
+ void 0,
1072
+ query,
1073
+ mergedOptions
1074
+ );
1075
+ }
1076
+ function createAuthClient(config = {}) {
1077
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
1078
+ const resolvedConfig = {
1079
+ ...config,
1080
+ baseUrl: normalizedBaseUrl
1081
+ };
1082
+ const request = (input, options) => {
1083
+ const method = input.method ?? (input.body !== void 0 ? "POST" : inferDefaultMethod(input.endpoint));
1084
+ const mergedOptions = mergeCallOptions(input.fetchOptions, options);
1085
+ return callAuthEndpoint(
1086
+ resolvedConfig,
1087
+ { endpoint: input.endpoint, method },
1088
+ input.body,
1089
+ input.query,
1090
+ mergedOptions
1091
+ );
1092
+ };
1093
+ const postGeneric = (endpoint, input, options) => {
1094
+ const { payload, fetchOptions } = extractFetchOptions(input);
1095
+ return request(
1096
+ {
1097
+ endpoint,
1098
+ method: "POST",
1099
+ body: payload ?? {},
1100
+ fetchOptions
1101
+ },
1102
+ options
1103
+ );
1104
+ };
1105
+ const getGeneric = (endpoint, input, options) => {
1106
+ const { fetchOptions } = extractFetchOptions(input);
1107
+ return request(
1108
+ {
1109
+ endpoint,
1110
+ method: "GET",
1111
+ fetchOptions
1112
+ },
1113
+ options
1114
+ );
1115
+ };
1116
+ const getWithQuery = (endpoint, input, options) => {
1117
+ const { payload, fetchOptions } = extractFetchOptions(input);
1118
+ const query = payload?.query;
1119
+ return request(
1120
+ {
1121
+ endpoint,
1122
+ method: "GET",
1123
+ query,
1124
+ fetchOptions
1125
+ },
1126
+ options
1127
+ );
1128
+ };
1129
+ const withReactEmailRoute = (route) => ({
1130
+ ...resolvedConfig.reactEmail,
1131
+ route
1132
+ });
1133
+ const resolveAdminEmailPayload = (route, input) => resolveReactEmailPayloadFields(input, {
1134
+ htmlField: "htmlBody",
1135
+ textField: "textBody"
1136
+ }, withReactEmailRoute(route));
1137
+ const resolveAdminEmailTemplatePayload = (route, input) => resolveReactEmailPayloadFields(input, {
1138
+ htmlField: "htmlTemplate",
1139
+ textField: "textTemplate",
1140
+ variablesField: "variables"
1141
+ }, withReactEmailRoute(route));
1142
+ const listUserEmailsWithFallback = async (input, options) => {
1143
+ const primary = await getWithQuery(
1144
+ "/email/list",
1145
+ input,
1146
+ options
1147
+ );
1148
+ if (primary.ok || primary.status !== 404 || primary.errorDetails?.code !== "HTTP_ERROR") {
1149
+ return primary;
1150
+ }
1151
+ return getWithQuery(
1152
+ "/email-list",
1153
+ input,
1154
+ options
1155
+ );
1156
+ };
1157
+ const healthWithFallback = async (input, options) => {
1158
+ const primary = await getGeneric("/health", input, options);
1159
+ if (primary.ok || primary.status !== 404 || primary.errorDetails?.code !== "HTTP_ERROR") {
1160
+ return primary;
1161
+ }
1162
+ const fallback = await getGeneric("/ok", input, options);
1163
+ if (!fallback.ok) {
1164
+ return {
1165
+ ...fallback,
1166
+ data: null
1167
+ };
1168
+ }
1169
+ const fallbackStatus = isRecord3(fallback.data) && typeof fallback.data.ok === "boolean" ? fallback.data.ok ? "ok" : "error" : "ok";
1170
+ return {
1171
+ ...fallback,
1172
+ data: {
1173
+ status: fallbackStatus
1174
+ }
1175
+ };
1176
+ };
1177
+ const signOut = (input, options) => executePostWithOptionalInput(
1178
+ resolvedConfig,
1179
+ { endpoint: "/sign-out", method: "POST" },
1180
+ input,
1181
+ options
1182
+ );
1183
+ const revokeSessions = (input, options) => executePostWithOptionalInput(
1184
+ resolvedConfig,
1185
+ { endpoint: "/revoke-sessions", method: "POST" },
1186
+ input,
1187
+ options
1188
+ );
1189
+ const revokeOtherSessions = (input, options) => executePostWithOptionalInput(
1190
+ resolvedConfig,
1191
+ { endpoint: "/revoke-other-sessions", method: "POST" },
1192
+ input,
1193
+ options
1194
+ );
1195
+ const revokeSession = (input, options) => executePostWithCompatibleInput(
1196
+ resolvedConfig,
1197
+ { endpoint: "/revoke-session", method: "POST" },
1198
+ input,
1199
+ options
1200
+ );
1201
+ const deleteUser = (input, options) => {
1202
+ const { payload, fetchOptions } = extractFetchOptions(input);
1203
+ const mergedOptions = mergeCallOptions(fetchOptions, options);
1204
+ return callAuthEndpoint(
1205
+ resolvedConfig,
1206
+ { endpoint: "/delete-user", method: "POST" },
1207
+ payload ?? {},
1208
+ void 0,
1209
+ mergedOptions
1210
+ );
1211
+ };
1212
+ const deleteUserCallback = (input, options) => {
1213
+ const { payload, fetchOptions } = extractFetchOptions(input);
1214
+ const mergedOptions = mergeCallOptions(fetchOptions, options);
1215
+ const query = payload ?? {};
1216
+ return callAuthEndpoint(
1217
+ resolvedConfig,
1218
+ { endpoint: "/delete-user/callback", method: "GET" },
1219
+ void 0,
1220
+ {
1221
+ token: query.token,
1222
+ callbackURL: query.callbackURL
1223
+ },
1224
+ mergedOptions
1225
+ );
1226
+ };
1227
+ const resolveResetPasswordToken = (input, options) => {
1228
+ const { payload, fetchOptions } = extractFetchOptions(input);
1229
+ const mergedOptions = mergeCallOptions(fetchOptions, options);
1230
+ const query = payload;
1231
+ const token = query?.token?.trim();
1232
+ if (!token) {
1233
+ throw new Error("resolveResetPasswordToken requires a non-empty token");
1234
+ }
1235
+ const endpoint = `/reset-password/${encodeURIComponent(token)}`;
1236
+ return callAuthEndpoint(
1237
+ resolvedConfig,
1238
+ { endpoint, method: "GET" },
1239
+ void 0,
1240
+ query?.callbackURL ? { callbackURL: query.callbackURL } : void 0,
1241
+ mergedOptions
1242
+ );
1243
+ };
1244
+ const organization = {
1245
+ create: (input, options) => executePostWithCompatibleInput(
1246
+ resolvedConfig,
1247
+ { endpoint: "/organization/create", method: "POST" },
1248
+ input,
1249
+ options
1250
+ ),
1251
+ update: (input, options) => executePostWithCompatibleInput(
1252
+ resolvedConfig,
1253
+ { endpoint: "/organization/update", method: "POST" },
1254
+ input,
1255
+ options
1256
+ ),
1257
+ delete: (input, options) => executePostWithCompatibleInput(
1258
+ resolvedConfig,
1259
+ { endpoint: "/organization/delete", method: "POST" },
1260
+ input,
1261
+ options
1262
+ ),
1263
+ setActive: (input, options) => executePostWithCompatibleInput(
1264
+ resolvedConfig,
1265
+ { endpoint: "/organization/set-active", method: "POST" },
1266
+ input,
1267
+ options
1268
+ ),
1269
+ list: (input, options) => getGeneric(
1270
+ "/organization/list",
1271
+ input,
1272
+ options
1273
+ ),
1274
+ getFull: (input, options) => executeGetWithQueryCompatibleInput(
1275
+ resolvedConfig,
1276
+ { endpoint: "/organization/get-full-organization", method: "GET" },
1277
+ input,
1278
+ options
1279
+ ),
1280
+ checkSlug: (input, options) => executePostWithCompatibleInput(
1281
+ resolvedConfig,
1282
+ { endpoint: "/organization/check-slug", method: "POST" },
1283
+ input,
1284
+ options
1285
+ ),
1286
+ leave: (input, options) => executePostWithCompatibleInput(
1287
+ resolvedConfig,
1288
+ { endpoint: "/organization/leave", method: "POST" },
1289
+ input,
1290
+ options
1291
+ ),
1292
+ listUserInvitations: (input, options) => executeGetWithQueryCompatibleInput(
1293
+ resolvedConfig,
1294
+ { endpoint: "/organization/list-user-invitations", method: "GET" },
1295
+ input,
1296
+ options
1297
+ ),
1298
+ hasPermission: (input, options) => postGeneric(
1299
+ "/organization/has-permission",
1300
+ input,
1301
+ options
1302
+ ),
1303
+ invitation: {
1304
+ cancel: (input, options) => executePostWithCompatibleInput(
1305
+ resolvedConfig,
1306
+ { endpoint: "/organization/cancel-invitation", method: "POST" },
1307
+ input,
1308
+ options
1309
+ ),
1310
+ accept: (input, options) => executePostWithCompatibleInput(
1311
+ resolvedConfig,
1312
+ { endpoint: "/organization/accept-invitation", method: "POST" },
1313
+ input,
1314
+ options
1315
+ ),
1316
+ get: (input, options) => executeGetWithQueryCompatibleInput(
1317
+ resolvedConfig,
1318
+ { endpoint: "/organization/get-invitation", method: "GET" },
1319
+ input,
1320
+ options
1321
+ ),
1322
+ reject: (input, options) => executePostWithCompatibleInput(
1323
+ resolvedConfig,
1324
+ { endpoint: "/organization/reject-invitation", method: "POST" },
1325
+ input,
1326
+ options
1327
+ ),
1328
+ list: (input, options) => executeGetWithQueryCompatibleInput(
1329
+ resolvedConfig,
1330
+ { endpoint: "/organization/list-invitations", method: "GET" },
1331
+ input,
1332
+ options
1333
+ )
1334
+ },
1335
+ member: {
1336
+ remove: (input, options) => executePostWithCompatibleInput(
1337
+ resolvedConfig,
1338
+ { endpoint: "/organization/remove-member", method: "POST" },
1339
+ input,
1340
+ options
1341
+ ),
1342
+ updateRole: (input, options) => executePostWithCompatibleInput(
1343
+ resolvedConfig,
1344
+ { endpoint: "/organization/update-member-role", method: "POST" },
1345
+ input,
1346
+ options
1347
+ ),
1348
+ invite: (input, options) => executePostWithCompatibleInput(
1349
+ resolvedConfig,
1350
+ { endpoint: "/organization/invite-member", method: "POST" },
1351
+ input,
1352
+ options
1353
+ ),
1354
+ getActive: (input, options) => executeGetWithCompatibleInput(
1355
+ resolvedConfig,
1356
+ { endpoint: "/organization/get-active-member", method: "GET" },
1357
+ input,
1358
+ options
1359
+ ),
1360
+ list: (input, options) => executeGetWithQueryCompatibleInput(
1361
+ resolvedConfig,
1362
+ { endpoint: "/organization/list-members", method: "GET" },
1363
+ input,
1364
+ options
1365
+ )
1366
+ }
1367
+ };
1368
+ const authResetPassword = Object.assign(
1369
+ (input, options) => executePostWithCompatibleInput(
1370
+ resolvedConfig,
1371
+ { endpoint: "/reset-password", method: "POST" },
1372
+ input,
1373
+ options
1374
+ ),
1375
+ {
1376
+ token: resolveResetPasswordToken
1377
+ }
1378
+ );
1379
+ const sessionRevokeBinding = (input, options) => {
1380
+ if (Array.isArray(input)) {
1381
+ if (input.length === 0) {
1382
+ throw new Error("session.revoke requires at least one session token");
1383
+ }
1384
+ if (input.length === 1) {
1385
+ return revokeSession(input[0], options);
1386
+ }
1387
+ return revokeSessions(void 0, options);
1388
+ }
1389
+ const parsed = input;
1390
+ const tokens = Array.isArray(parsed.tokens) ? parsed.tokens.filter((token2) => token2.trim().length > 0) : void 0;
1391
+ if (tokens && tokens.length > 1) {
1392
+ return revokeSessions(
1393
+ parsed.fetchOptions ? { fetchOptions: parsed.fetchOptions } : void 0,
1394
+ options
1395
+ );
1396
+ }
1397
+ if (tokens && tokens.length === 1) {
1398
+ return revokeSession(
1399
+ { token: tokens[0], fetchOptions: parsed.fetchOptions },
1400
+ options
1401
+ );
1402
+ }
1403
+ const token = parsed.token?.trim();
1404
+ if (!token) {
1405
+ throw new Error("session.revoke requires a non-empty token or a non-empty token list");
1406
+ }
1407
+ return revokeSession(
1408
+ {
1409
+ token,
1410
+ fetchOptions: parsed.fetchOptions
1411
+ },
1412
+ options
1413
+ );
1414
+ };
1415
+ const adminUserSessionRevokeBinding = (input, options) => {
1416
+ const requireUserId = (userId) => {
1417
+ const trimmed = String(userId ?? "").trim();
1418
+ if (!trimmed) {
1419
+ throw new Error("admin.user.session.revoke requires a non-empty userId");
1420
+ }
1421
+ return trimmed;
1422
+ };
1423
+ const requireSinglePluralUserId = (sessions2) => {
1424
+ const uniqueUserIds = [...new Set(sessions2.map((session) => requireUserId(session.userId)))];
1425
+ if (uniqueUserIds.length !== 1) {
1426
+ throw new Error("admin.user.session.revoke requires the same userId across plural payloads");
1427
+ }
1428
+ return { userId: uniqueUserIds[0] };
1429
+ };
1430
+ if (Array.isArray(input)) {
1431
+ if (input.length === 0) {
1432
+ throw new Error("admin.user.session.revoke requires at least one payload item");
1433
+ }
1434
+ if (input.length === 1) {
1435
+ return postGeneric(
1436
+ "/admin/revoke-user-session",
1437
+ {
1438
+ ...input[0],
1439
+ userId: requireUserId(input[0].userId)
1440
+ },
1441
+ options
1442
+ );
1443
+ }
1444
+ return postGeneric(
1445
+ "/admin/revoke-user-sessions",
1446
+ requireSinglePluralUserId(input),
1447
+ options
1448
+ );
1449
+ }
1450
+ const parsed = input;
1451
+ const sessions = parsed.sessions;
1452
+ if (sessions && sessions.length === 0) {
1453
+ throw new Error("admin.user.session.revoke requires at least one payload item");
1454
+ }
1455
+ if (sessions && sessions.length === 1) {
1456
+ return postGeneric(
1457
+ "/admin/revoke-user-session",
1458
+ {
1459
+ ...sessions[0],
1460
+ userId: requireUserId(sessions[0].userId),
1461
+ fetchOptions: parsed.fetchOptions
1462
+ },
1463
+ options
1464
+ );
1465
+ }
1466
+ if (sessions && sessions.length > 1) {
1467
+ return postGeneric(
1468
+ "/admin/revoke-user-sessions",
1469
+ {
1470
+ ...requireSinglePluralUserId(sessions),
1471
+ fetchOptions: parsed.fetchOptions
1472
+ },
1473
+ options
1474
+ );
1475
+ }
1476
+ const normalizedUserId = requireUserId(parsed.userId);
1477
+ if (!parsed.sessionToken) {
1478
+ return postGeneric(
1479
+ "/admin/revoke-user-sessions",
1480
+ {
1481
+ userId: normalizedUserId,
1482
+ fetchOptions: parsed.fetchOptions
1483
+ },
1484
+ options
1485
+ );
1486
+ }
1487
+ return postGeneric(
1488
+ "/admin/revoke-user-session",
1489
+ {
1490
+ ...parsed,
1491
+ userId: normalizedUserId
1492
+ },
1493
+ options
1494
+ );
1495
+ };
1496
+ const auth = {
1497
+ getSession: (input, options) => getGeneric("/get-session", input, options),
1498
+ signOut,
1499
+ forgetPassword: (input, options) => postGeneric("/forget-password", input, options),
1500
+ resetPassword: authResetPassword,
1501
+ setPassword: (input, options) => postGeneric("/set-password", input, options),
1502
+ verifyEmail: (input, options) => {
1503
+ const queryInput = {
1504
+ query: {
1505
+ token: input.token,
1506
+ callbackURL: input.callbackURL
1507
+ },
1508
+ fetchOptions: input.fetchOptions
1509
+ };
1510
+ return getWithQuery(
1511
+ "/verify-email",
1512
+ queryInput,
1513
+ options
1514
+ );
1515
+ },
1516
+ sendVerificationEmail: (input, options) => postGeneric("/send-verification-email", input, options),
1517
+ changeEmail: (input, options) => postGeneric("/change-email", input, options),
1518
+ changeEmailVerify: (input, options) => getWithQuery("/change-email/verify", input, options),
1519
+ deleteUserVerify: (input, options) => getWithQuery("/delete-user/verify", input, options),
1520
+ changePassword: (input, options) => postGeneric("/change-password", input, options),
1521
+ user: {
1522
+ update: (input, options) => postGeneric("/update-user", input, options),
1523
+ delete: (input, options) => postGeneric("/delete-user", input, options),
1524
+ email: {
1525
+ list: listUserEmailsWithFallback
1526
+ }
1527
+ },
1528
+ session: {
1529
+ list: (input, options) => getGeneric("/list-sessions", input, options),
1530
+ revoke: sessionRevokeBinding,
1531
+ revokeOther: revokeOtherSessions
1532
+ },
1533
+ social: {
1534
+ link: (input, options) => postGeneric("/link-social", input, options)
1535
+ },
1536
+ account: {
1537
+ list: (input, options) => getGeneric("/list-accounts", input, options),
1538
+ unlink: (input, options) => postGeneric("/unlink-account", input, options)
1539
+ },
1540
+ deleteUser: {
1541
+ callback: deleteUserCallback
1542
+ },
1543
+ refreshToken: (input, options) => postGeneric("/refresh-token", input, options),
1544
+ getAccessToken: (input, options) => postGeneric("/get-access-token", input, options),
1545
+ health: healthWithFallback,
1546
+ ok: (input, options) => getGeneric("/ok", input, options),
1547
+ error: (input, options) => getGeneric("/error", input, options),
1548
+ twoFactor: {
1549
+ getTotpUri: (input, options) => postGeneric("/two-factor/get-totp-uri", input, options),
1550
+ verifyTotp: (input, options) => postGeneric("/two-factor/verify-totp", input, options),
1551
+ sendOtp: (input, options) => postGeneric("/two-factor/send-otp", input, options),
1552
+ verifyOtp: (input, options) => postGeneric("/two-factor/verify-otp", input, options),
1553
+ verifyBackupCode: (input, options) => postGeneric("/two-factor/verify-backup-code", input, options),
1554
+ generateBackupCodes: (input, options) => executePostWithCompatibleInput(
1555
+ resolvedConfig,
1556
+ { endpoint: "/two-factor/generate-backup-codes", method: "POST" },
1557
+ input,
1558
+ options
1559
+ ),
1560
+ enable: (input, options) => postGeneric("/two-factor/enable", input, options),
1561
+ disable: (input, options) => postGeneric("/two-factor/disable", input, options)
1562
+ },
1563
+ passkey: {
1564
+ generateRegisterOptions: (input, options) => getGeneric("/passkey/generate-register-options", input, options),
1565
+ generateAuthenticateOptions: (input, options) => postGeneric("/passkey/generate-authenticate-options", input, options),
1566
+ verifyRegistration: (input, options) => postGeneric("/passkey/verify-registration", input, options),
1567
+ verifyAuthentication: (input, options) => postGeneric("/passkey/verify-authentication", input, options),
1568
+ listUserPasskeys: (input, options) => getGeneric("/passkey/list-user-passkeys", input, options),
1569
+ deletePasskey: (input, options) => postGeneric("/passkey/delete-passkey", input, options),
1570
+ updatePasskey: (input, options) => postGeneric("/passkey/update-passkey", input, options),
1571
+ getRelatedOrigins: (input, options) => getGeneric("/.well-known/webauthn", input, options)
1572
+ },
1573
+ admin: {
1574
+ role: {
1575
+ set: (input, options) => postGeneric("/admin/set-role", input, options)
1576
+ },
1577
+ user: {
1578
+ list: (input, options) => getWithQuery("/admin/list-users", input, options),
1579
+ create: (input, options) => postGeneric("/admin/create-user", input, options),
1580
+ unban: (input, options) => postGeneric("/admin/unban-user", input, options),
1581
+ ban: (input, options) => postGeneric("/admin/ban-user", input, options),
1582
+ impersonate: (input, options) => postGeneric("/admin/impersonate-user", input, options),
1583
+ stopImpersonating: (input, options) => postGeneric("/admin/stop-impersonating", input, options),
1584
+ remove: (input, options) => postGeneric("/admin/remove-user", input, options),
1585
+ setPassword: (input, options) => postGeneric("/admin/set-user-password", input, options),
1586
+ session: {
1587
+ list: (input, options) => postGeneric("/admin/list-user-sessions", input, options),
1588
+ revoke: adminUserSessionRevokeBinding
1589
+ }
1590
+ },
1591
+ hasPermission: (input, options) => postGeneric("/admin/has-permission", input, options),
1592
+ apiKey: {
1593
+ create: (input, options) => postGeneric("/admin/api-key/create", input, options)
1594
+ },
1595
+ athenaClient: {
1596
+ create: (input, options) => postGeneric("/admin/athena-client/create", input, options),
1597
+ list: (input, options) => getWithQuery("/admin/athena-client/list", input, options)
1598
+ },
1599
+ auditLog: {
1600
+ list: (input, options) => getWithQuery("/admin/audit-log/list", input, options)
1601
+ },
1602
+ email: {
1603
+ list: (input, options) => getWithQuery("/admin/email/list", input, options),
1604
+ get: (input, options) => getWithQuery("/admin/email/get", input, options),
1605
+ create: async (input, options) => postGeneric(
1606
+ "/admin/email/create",
1607
+ await resolveAdminEmailPayload("/admin/email/create", input),
1608
+ options
1609
+ ),
1610
+ update: async (input, options) => postGeneric(
1611
+ "/admin/email/update",
1612
+ await resolveAdminEmailPayload("/admin/email/update", input),
1613
+ options
1614
+ ),
1615
+ delete: (input, options) => postGeneric("/admin/email/delete", input, options),
1616
+ failure: {
1617
+ list: (input, options) => getWithQuery("/admin/email-failure/list", input, options),
1618
+ get: (input, options) => getWithQuery("/admin/email-failure/get", input, options),
1619
+ create: (input, options) => postGeneric("/admin/email-failure/create", input, options),
1620
+ update: (input, options) => postGeneric("/admin/email-failure/update", input, options),
1621
+ delete: (input, options) => postGeneric("/admin/email-failure/delete", input, options)
1622
+ },
1623
+ template: {
1624
+ list: (input, options) => getWithQuery("/admin/email-template/list", input, options),
1625
+ get: (input, options) => getWithQuery("/admin/email-template/get", input, options),
1626
+ create: async (input, options) => postGeneric(
1627
+ "/admin/email-template/create",
1628
+ await resolveAdminEmailTemplatePayload("/admin/email-template/create", input),
1629
+ options
1630
+ ),
1631
+ update: async (input, options) => postGeneric(
1632
+ "/admin/email-template/update",
1633
+ await resolveAdminEmailTemplatePayload("/admin/email-template/update", input),
1634
+ options
1635
+ ),
1636
+ delete: (input, options) => postGeneric("/admin/email-template/delete", input, options)
1637
+ }
1638
+ },
1639
+ emailTemplate: {
1640
+ get: (input, options) => getWithQuery("/admin/email-template/get", input, options),
1641
+ create: async (input, options) => postGeneric(
1642
+ "/admin/email-template/create",
1643
+ await resolveAdminEmailTemplatePayload("/admin/email-template/create", input),
1644
+ options
1645
+ ),
1646
+ delete: (input, options) => postGeneric("/admin/email-template/delete", input, options),
1647
+ list: (input, options) => getWithQuery("/admin/email-template/list", input, options),
1648
+ update: async (input, options) => postGeneric(
1649
+ "/admin/email-template/update",
1650
+ await resolveAdminEmailTemplatePayload("/admin/email-template/update", input),
1651
+ options
1652
+ )
1653
+ }
1654
+ },
1655
+ apiKey: {
1656
+ create: (input, options) => postGeneric("/api-key/create", input, options),
1657
+ get: (input, options) => getWithQuery("/api-key/get", input, options),
1658
+ update: (input, options) => postGeneric("/api-key/update", input, options),
1659
+ delete: (input, options) => postGeneric("/api-key/delete", input, options),
1660
+ list: (input, options) => getWithQuery("/api-key/list", input, options),
1661
+ verify: (input, options) => postGeneric("/api-key/verify", input, options),
1662
+ deleteAllExpired: (input, options) => executePostWithOptionalInput(
1663
+ resolvedConfig,
1664
+ { endpoint: "/api-key/delete-all-expired-api-keys", method: "POST" },
1665
+ input,
1666
+ options
1667
+ )
1668
+ },
1669
+ signIn: {
1670
+ email: (input, options) => postGeneric("/sign-in/email", input, options),
1671
+ username: (input, options) => postGeneric("/sign-in/username", input, options),
1672
+ social: (input, options) => postGeneric("/sign-in/social", input, options)
1673
+ },
1674
+ signUp: {
1675
+ email: (input, options) => postGeneric("/sign-up/email", input, options)
1676
+ },
1677
+ organization,
1678
+ callback: {
1679
+ provider: (input, options) => {
1680
+ const { payload, fetchOptions } = extractFetchOptions(input);
1681
+ const parsed = payload;
1682
+ const provider = String(parsed?.provider ?? "").trim();
1683
+ if (!provider) {
1684
+ throw new Error("callback.provider requires a non-empty provider value");
1685
+ }
1686
+ const code = String(parsed?.code ?? "").trim();
1687
+ const state = String(parsed?.state ?? "").trim();
1688
+ if (!code || !state) {
1689
+ throw new Error("callback.provider requires non-empty code and state values");
1690
+ }
1691
+ const endpoint = `/callback/${encodeURIComponent(provider)}`;
1692
+ return request({
1693
+ endpoint,
1694
+ method: "GET",
1695
+ query: {
1696
+ code,
1697
+ state
1698
+ },
1699
+ fetchOptions
1700
+ }, options);
1701
+ }
1702
+ }
1703
+ };
1704
+ return {
1705
+ baseUrl: normalizedBaseUrl,
1706
+ request,
1707
+ signIn: {
1708
+ email: (input, options) => executePostWithCompatibleInput(
1709
+ resolvedConfig,
1710
+ { endpoint: "/sign-in/email", method: "POST" },
1711
+ input,
1712
+ options
1713
+ ),
1714
+ username: (input, options) => executePostWithCompatibleInput(
1715
+ resolvedConfig,
1716
+ { endpoint: "/sign-in/username", method: "POST" },
1717
+ input,
1718
+ options
1719
+ ),
1720
+ social: (input, options) => executePostWithCompatibleInput(
1721
+ resolvedConfig,
1722
+ { endpoint: "/sign-in/social", method: "POST" },
1723
+ input,
1724
+ options
1725
+ )
1726
+ },
1727
+ signUp: {
1728
+ email: (input, options) => executePostWithCompatibleInput(
1729
+ resolvedConfig,
1730
+ { endpoint: "/sign-up/email", method: "POST" },
1731
+ input,
1732
+ options
1733
+ )
1734
+ },
1735
+ signOut,
1736
+ logout: signOut,
1737
+ getSession: (input, options) => executeGetWithCompatibleInput(
1738
+ resolvedConfig,
1739
+ { endpoint: "/get-session", method: "GET" },
1740
+ input,
1741
+ options
1742
+ ),
1743
+ listSessions: (input, options) => executeGetWithCompatibleInput(
1744
+ resolvedConfig,
1745
+ { endpoint: "/list-sessions", method: "GET" },
1746
+ input,
1747
+ options
1748
+ ),
1749
+ revokeSession,
1750
+ clearSession: revokeSession,
1751
+ revokeSessions,
1752
+ clearSessions: revokeSessions,
1753
+ revokeOtherSessions,
1754
+ clearOtherSessions: revokeOtherSessions,
1755
+ forgetPassword: (input, options) => executePostWithCompatibleInput(
1756
+ resolvedConfig,
1757
+ { endpoint: "/forget-password", method: "POST" },
1758
+ input,
1759
+ options
1760
+ ),
1761
+ resetPassword: (input, options) => executePostWithCompatibleInput(
1762
+ resolvedConfig,
1763
+ { endpoint: "/reset-password", method: "POST" },
1764
+ input,
1765
+ options
1766
+ ),
1767
+ resolveResetPasswordToken,
1768
+ verifyEmail: (input, options) => {
1769
+ const { payload, fetchOptions } = extractFetchOptions(input);
1770
+ const mergedOptions = mergeCallOptions(fetchOptions, options);
1771
+ const query = payload;
1772
+ return callAuthEndpoint(
1773
+ resolvedConfig,
1774
+ { endpoint: "/verify-email", method: "GET" },
1775
+ void 0,
1776
+ query ? {
1777
+ token: query.token,
1778
+ callbackURL: query.callbackURL
1779
+ } : void 0,
1780
+ mergedOptions
1781
+ );
1782
+ },
1783
+ sendVerificationEmail: (input, options) => executePostWithCompatibleInput(
1784
+ resolvedConfig,
1785
+ { endpoint: "/send-verification-email", method: "POST" },
1786
+ input,
1787
+ options
1788
+ ),
1789
+ changeEmail: (input, options) => executePostWithCompatibleInput(
1790
+ resolvedConfig,
1791
+ { endpoint: "/change-email", method: "POST" },
1792
+ input,
1793
+ options
1794
+ ),
1795
+ changePassword: (input, options) => executePostWithCompatibleInput(
1796
+ resolvedConfig,
1797
+ { endpoint: "/change-password", method: "POST" },
1798
+ input,
1799
+ options
1800
+ ),
1801
+ updateUser: (input, options) => executePostWithCompatibleInput(
1802
+ resolvedConfig,
1803
+ { endpoint: "/update-user", method: "POST" },
1804
+ input,
1805
+ options
1806
+ ),
1807
+ deleteUser,
1808
+ deleteUserCallback,
1809
+ linkSocial: (input, options) => executePostWithCompatibleInput(
1810
+ resolvedConfig,
1811
+ { endpoint: "/link-social", method: "POST" },
1812
+ input,
1813
+ options
1814
+ ),
1815
+ listAccounts: (input, options) => executeGetWithCompatibleInput(
1816
+ resolvedConfig,
1817
+ { endpoint: "/list-accounts", method: "GET" },
1818
+ input,
1819
+ options
1820
+ ),
1821
+ unlinkAccount: (input, options) => executePostWithCompatibleInput(
1822
+ resolvedConfig,
1823
+ { endpoint: "/unlink-account", method: "POST" },
1824
+ input,
1825
+ options
1826
+ ),
1827
+ refreshToken: (input, options) => executePostWithCompatibleInput(
1828
+ resolvedConfig,
1829
+ { endpoint: "/refresh-token", method: "POST" },
1830
+ input,
1831
+ options
1832
+ ),
1833
+ getAccessToken: (input, options) => executePostWithCompatibleInput(
1834
+ resolvedConfig,
1835
+ { endpoint: "/get-access-token", method: "POST" },
1836
+ input,
1837
+ options
1838
+ ),
1839
+ organization,
1840
+ auth
1841
+ };
1842
+ }
1843
+
1844
+ // src/utils/parse-boolean-flag.ts
1845
+ function parseBooleanFlag(rawValue, fallback) {
1846
+ if (!rawValue) return fallback;
1847
+ const normalized = rawValue.trim().toLowerCase();
1848
+ if (normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on") {
1849
+ return true;
1850
+ }
1851
+ if (normalized === "0" || normalized === "false" || normalized === "no" || normalized === "off") {
1852
+ return false;
1853
+ }
1854
+ return fallback;
1855
+ }
1856
+
1857
+ // src/auxiliaries.ts
1858
+ var AthenaErrorKind = {
1859
+ UniqueViolation: "unique_violation",
1860
+ NotFound: "not_found",
1861
+ Validation: "validation",
1862
+ Auth: "auth",
1863
+ RateLimit: "rate_limit",
1864
+ Transient: "transient",
1865
+ Unknown: "unknown"
1866
+ };
1867
+ var AthenaErrorCode = {
1868
+ UniqueViolation: "UNIQUE_VIOLATION",
1869
+ NotFound: "NOT_FOUND",
1870
+ ValidationFailed: "VALIDATION_FAILED",
1871
+ AuthUnauthorized: "AUTH_UNAUTHORIZED",
1872
+ AuthForbidden: "AUTH_FORBIDDEN",
1873
+ RateLimited: "RATE_LIMITED",
1874
+ NetworkUnavailable: "NETWORK_UNAVAILABLE",
1875
+ TransientFailure: "TRANSIENT_FAILURE",
1876
+ HttpFailure: "HTTP_FAILURE",
1877
+ Unknown: "UNKNOWN"
1878
+ };
1879
+ var AthenaErrorCategory = {
1880
+ Transport: "transport",
1881
+ Client: "client",
1882
+ Server: "server",
1883
+ Database: "database",
1884
+ Unknown: "unknown"
1885
+ };
1886
+ function parseBooleanFlag2(rawValue, fallback) {
1887
+ return parseBooleanFlag(rawValue, fallback);
1888
+ }
1889
+ var AthenaError = class extends Error {
1890
+ code;
1891
+ kind;
1892
+ category;
1893
+ status;
1894
+ retryable;
1895
+ requestId;
1896
+ context;
1897
+ raw;
1898
+ constructor(input) {
1899
+ super(input.message);
1900
+ this.name = "AthenaError";
1901
+ this.code = input.code;
1902
+ this.kind = input.kind;
1903
+ this.category = input.category;
1904
+ this.status = input.status;
1905
+ this.retryable = input.retryable ?? false;
1906
+ this.requestId = input.requestId;
1907
+ this.context = input.context;
1908
+ this.raw = input.raw;
1909
+ }
1910
+ };
1911
+ function isRecord4(value) {
1912
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1913
+ }
1914
+ function firstNonEmptyString(...values) {
1915
+ for (const value of values) {
1916
+ if (typeof value === "string" && value.trim().length > 0) {
1917
+ return value.trim();
1918
+ }
1919
+ }
1920
+ return void 0;
1921
+ }
1922
+ function messageFromUnknownError(error) {
1923
+ if (typeof error === "string" && error.trim().length > 0) {
1924
+ return error.trim();
1925
+ }
1926
+ if (error instanceof Error && error.message.trim().length > 0) {
1927
+ return error.message.trim();
1928
+ }
1929
+ if (!isRecord4(error)) {
1930
+ return void 0;
1931
+ }
1932
+ return firstNonEmptyString(error.message, error.error, error.details);
1933
+ }
1934
+ function gatewayCodeFromUnknownError(error) {
1935
+ if (!isRecord4(error) || typeof error.gatewayCode !== "string") {
1936
+ return void 0;
1937
+ }
1938
+ return error.gatewayCode;
1939
+ }
1940
+ function isAthenaResultErrorLike(value) {
1941
+ return isRecord4(value) && typeof value.message === "string" && (value.athenaCode === void 0 || isAthenaErrorCode(value.athenaCode)) && (value.kind === void 0 || isAthenaErrorKind(value.kind)) && (value.category === void 0 || isAthenaErrorCategory(value.category)) && (value.retryable === void 0 || typeof value.retryable === "boolean") && (value.status === void 0 || typeof value.status === "number");
1942
+ }
1943
+ function isAthenaErrorKind(value) {
1944
+ return value === "unique_violation" || value === "not_found" || value === "validation" || value === "auth" || value === "rate_limit" || value === "transient" || value === "unknown";
1945
+ }
1946
+ function isAthenaErrorCode(value) {
1947
+ return value === "UNIQUE_VIOLATION" || value === "NOT_FOUND" || value === "VALIDATION_FAILED" || value === "AUTH_UNAUTHORIZED" || value === "AUTH_FORBIDDEN" || value === "RATE_LIMITED" || value === "NETWORK_UNAVAILABLE" || value === "TRANSIENT_FAILURE" || value === "HTTP_FAILURE" || value === "UNKNOWN";
1948
+ }
1949
+ function isAthenaErrorCategory(value) {
1950
+ return value === "transport" || value === "client" || value === "server" || value === "database" || value === "unknown";
1951
+ }
1952
+ function isNormalizedAthenaError(value) {
1953
+ return isRecord4(value) && isAthenaErrorKind(value.kind) && isAthenaErrorCode(value.code) && isAthenaErrorCategory(value.category) && typeof value.retryable === "boolean" && typeof value.message === "string" && "raw" in value;
1954
+ }
1955
+ function withContextOverrides(normalized, context) {
1956
+ if (!context?.table && !context?.operation) {
1957
+ return normalized;
1958
+ }
1959
+ return {
1960
+ ...normalized,
1961
+ table: context.table ?? normalized.table,
1962
+ operation: context.operation ?? normalized.operation
1963
+ };
1964
+ }
1965
+ function resolveAttachedNormalizedError(resultOrError) {
1966
+ if (!isRecord4(resultOrError)) return void 0;
1967
+ if (!("__athenaNormalizedError" in resultOrError)) return void 0;
1968
+ const candidate = resultOrError.__athenaNormalizedError;
1969
+ return isNormalizedAthenaError(candidate) ? candidate : void 0;
1970
+ }
1971
+ function safeStringify(value) {
1972
+ try {
1973
+ const serialized = JSON.stringify(value);
1974
+ return serialized ?? String(value);
1975
+ } catch {
1976
+ return "[unserializable]";
1977
+ }
1978
+ }
1979
+ function contextHint(context) {
1980
+ if (!context?.identity) return void 0;
1981
+ const identity = typeof context.identity === "string" ? context.identity : safeStringify(context.identity);
1982
+ return `Identity: ${identity}`;
1983
+ }
1984
+ function isAthenaResultLike(value) {
1985
+ return isRecord4(value) && "status" in value && "error" in value && "data" in value && typeof value.status === "number";
1986
+ }
1987
+ function operationFromDetails(details) {
1988
+ if (!details?.endpoint) return void 0;
1989
+ if (details.endpoint === "/gateway/fetch" || details.endpoint === "/gateway/query") return "select";
1990
+ if (details.endpoint === "/gateway/insert") return "insert";
1991
+ if (details.endpoint === "/gateway/update") return "update";
1992
+ if (details.endpoint === "/gateway/delete") return "delete";
1993
+ if (details.endpoint === "/gateway/rpc" || details.endpoint.startsWith("/rpc/")) return "rpc";
1994
+ return void 0;
1995
+ }
1996
+ function matchRegex(input, patterns) {
1997
+ for (const pattern of patterns) {
1998
+ const match = pattern.exec(input);
1999
+ if (match?.[1]) return match[1];
2000
+ }
2001
+ return void 0;
2002
+ }
2003
+ function extractConstraint(message) {
2004
+ return matchRegex(message, [
2005
+ /unique constraint\s+["'`]([^"'`]+)["'`]/i,
2006
+ /constraint\s+["'`]([^"'`]+)["'`]/i
2007
+ ]);
2008
+ }
2009
+ function extractTable(message) {
2010
+ return matchRegex(message, [
2011
+ /(?:table|relation)\s+["'`]([^"'`]+)["'`]/i,
2012
+ /on\s+table\s+([a-zA-Z0-9_.]+)/i
2013
+ ]);
2014
+ }
2015
+ function classifyKind(status, code, message) {
2016
+ const lower = message.toLowerCase();
2017
+ const hasUniquePattern = lower.includes("unique constraint") || lower.includes("duplicate key") || lower.includes("already exists") || lower.includes("duplicate");
2018
+ const hasNotFoundPattern = lower.includes("not found") || lower.includes("no rows");
2019
+ const hasValidationPattern = lower.includes("validation") || lower.includes("invalid") || lower.includes("malformed");
2020
+ const hasAuthPattern = lower.includes("unauthorized") || lower.includes("forbidden") || lower.includes("auth");
2021
+ const hasRateLimitPattern = lower.includes("rate limit") || lower.includes("too many requests");
2022
+ const hasTransientPattern = lower.includes("timeout") || lower.includes("temporar") || lower.includes("connection reset") || lower.includes("socket") || lower.includes("deadlock");
2023
+ if (status === 409 || hasUniquePattern) return "unique_violation";
2024
+ if (status === 404 || hasNotFoundPattern) return "not_found";
2025
+ if (status === 401 || status === 403 || hasAuthPattern) return "auth";
2026
+ if (status === 429 || hasRateLimitPattern) return "rate_limit";
2027
+ if (status === 400 || status === 422 || hasValidationPattern) return "validation";
2028
+ if (code === "NETWORK_ERROR" || status === 0 || status !== void 0 && status >= 500 || hasTransientPattern) {
2029
+ return "transient";
2030
+ }
2031
+ return "unknown";
2032
+ }
2033
+ function toAthenaErrorCode(kind, status, gatewayCode) {
2034
+ if (gatewayCode === "NETWORK_ERROR" || kind === "transient" && status === 0) {
2035
+ return AthenaErrorCode.NetworkUnavailable;
2036
+ }
2037
+ switch (kind) {
2038
+ case "unique_violation":
2039
+ return AthenaErrorCode.UniqueViolation;
2040
+ case "not_found":
2041
+ return AthenaErrorCode.NotFound;
2042
+ case "validation":
2043
+ return AthenaErrorCode.ValidationFailed;
2044
+ case "rate_limit":
2045
+ return AthenaErrorCode.RateLimited;
2046
+ case "auth":
2047
+ if (status === 403) {
2048
+ return AthenaErrorCode.AuthForbidden;
2049
+ }
2050
+ return AthenaErrorCode.AuthUnauthorized;
2051
+ case "transient":
2052
+ return status !== void 0 && status >= 500 ? AthenaErrorCode.HttpFailure : AthenaErrorCode.TransientFailure;
2053
+ case "unknown":
2054
+ default:
2055
+ return status !== void 0 && status >= 400 ? AthenaErrorCode.HttpFailure : AthenaErrorCode.Unknown;
2056
+ }
2057
+ }
2058
+ function toAthenaErrorCategory(kind, status) {
2059
+ if (kind === "transient" && (status === 0 || status === void 0)) {
2060
+ return AthenaErrorCategory.Transport;
2061
+ }
2062
+ if (kind === "unique_violation") return AthenaErrorCategory.Database;
2063
+ if (kind === "validation" || kind === "auth" || kind === "not_found") return AthenaErrorCategory.Client;
2064
+ if (kind === "rate_limit" || kind === "transient") return AthenaErrorCategory.Server;
2065
+ return AthenaErrorCategory.Unknown;
2066
+ }
2067
+ function isRetryable(kind, status) {
2068
+ if (kind === "rate_limit" || kind === "transient") return true;
2069
+ return status !== void 0 && status >= 500;
2070
+ }
2071
+ function toGatewayCode(kind, status) {
2072
+ if (kind === "transient" && (status === 0 || status === void 0)) return "NETWORK_ERROR";
2073
+ if (kind === "validation") return "INVALID_JSON";
2074
+ if (status !== void 0 && status >= 400) return "HTTP_ERROR";
2075
+ return "UNKNOWN_ERROR";
2076
+ }
2077
+ function toAthenaGatewayError(source, fallbackMessage, context) {
2078
+ if (isAthenaGatewayError(source)) {
2079
+ return source;
2080
+ }
2081
+ if (isAthenaResultLike(source) && source.errorDetails) {
2082
+ const message2 = messageFromUnknownError(source.error) ?? source.errorDetails.message ?? fallbackMessage;
2083
+ return new AthenaGatewayError({
2084
+ code: source.errorDetails.code,
2085
+ message: message2,
2086
+ status: source.status,
2087
+ endpoint: source.errorDetails.endpoint,
2088
+ method: source.errorDetails.method,
2089
+ requestId: source.errorDetails.requestId,
2090
+ hint: (isRecord4(source.error) ? firstNonEmptyString(source.error.hint) : void 0) ?? source.errorDetails.hint,
2091
+ cause: (isRecord4(source.error) ? firstNonEmptyString(source.error.cause) : void 0) ?? source.errorDetails.cause
2092
+ });
2093
+ }
2094
+ const normalized = normalizeAthenaError(source, context);
2095
+ const message = isAthenaResultLike(source) && source.error == null && source.errorDetails == null ? fallbackMessage : normalized.message || fallbackMessage;
2096
+ return new AthenaGatewayError({
2097
+ code: toGatewayCode(normalized.kind, normalized.status),
2098
+ message,
2099
+ status: normalized.status ?? 0,
2100
+ hint: normalized.constraint != null ? `Constraint: ${normalized.constraint}` : contextHint(context),
2101
+ cause: typeof normalized.raw === "string" ? normalized.raw : safeStringify(normalized.raw)
2102
+ });
2103
+ }
2104
+ function isOk(result) {
2105
+ return result.error == null && result.status >= 200 && result.status < 300;
2106
+ }
2107
+ function normalizeAthenaError(resultOrError, context) {
2108
+ const attached = resolveAttachedNormalizedError(resultOrError);
2109
+ if (attached) {
2110
+ return withContextOverrides(attached, context);
2111
+ }
2112
+ if (isAthenaResultLike(resultOrError)) {
2113
+ if (isAthenaResultErrorLike(resultOrError.error)) {
2114
+ return {
2115
+ kind: resultOrError.error.kind ?? classifyKind(resultOrError.status, gatewayCodeFromUnknownError(resultOrError.error), resultOrError.error.message),
2116
+ code: resultOrError.error.athenaCode ?? toAthenaErrorCode(
2117
+ resultOrError.error.kind ?? classifyKind(
2118
+ resultOrError.status,
2119
+ gatewayCodeFromUnknownError(resultOrError.error),
2120
+ resultOrError.error.message
2121
+ ),
2122
+ resultOrError.error.status ?? resultOrError.status,
2123
+ gatewayCodeFromUnknownError(resultOrError.error)
2124
+ ),
2125
+ category: resultOrError.error.category ?? toAthenaErrorCategory(
2126
+ resultOrError.error.kind ?? classifyKind(
2127
+ resultOrError.status,
2128
+ gatewayCodeFromUnknownError(resultOrError.error),
2129
+ resultOrError.error.message
2130
+ ),
2131
+ resultOrError.error.status ?? resultOrError.status
2132
+ ),
2133
+ retryable: resultOrError.error.retryable ?? isRetryable(
2134
+ resultOrError.error.kind ?? classifyKind(
2135
+ resultOrError.status,
2136
+ gatewayCodeFromUnknownError(resultOrError.error),
2137
+ resultOrError.error.message
2138
+ ),
2139
+ resultOrError.error.status ?? resultOrError.status
2140
+ ),
2141
+ status: resultOrError.error.status ?? resultOrError.status,
2142
+ constraint: resultOrError.error.constraint,
2143
+ table: context?.table ?? resultOrError.error.table,
2144
+ operation: context?.operation ?? resultOrError.error.operation,
2145
+ message: resultOrError.error.message,
2146
+ raw: resultOrError.error.raw ?? resultOrError.raw
2147
+ };
2148
+ }
2149
+ const details = resultOrError.errorDetails;
2150
+ const message2 = messageFromUnknownError(resultOrError.error) ?? details?.message ?? `Athena ${context?.operation ?? operationFromDetails(details) ?? "request"} failed`;
2151
+ const operation = context?.operation ?? operationFromDetails(details);
2152
+ const table = context?.table ?? extractTable(message2);
2153
+ const constraint = extractConstraint(message2);
2154
+ const gatewayCode = details?.code ?? gatewayCodeFromUnknownError(resultOrError.error);
2155
+ const kind2 = classifyKind(resultOrError.status, gatewayCode, message2);
2156
+ const code = toAthenaErrorCode(kind2, resultOrError.status, gatewayCode);
2157
+ const category = toAthenaErrorCategory(kind2, resultOrError.status);
2158
+ return {
2159
+ kind: kind2,
2160
+ code,
2161
+ category,
2162
+ retryable: isRetryable(kind2, resultOrError.status),
2163
+ status: resultOrError.status,
2164
+ constraint,
2165
+ table,
2166
+ operation,
2167
+ message: message2,
2168
+ raw: resultOrError.raw
2169
+ };
2170
+ }
2171
+ if (isAthenaGatewayError(resultOrError)) {
2172
+ const details = resultOrError.toDetails();
2173
+ const operation = context?.operation ?? operationFromDetails(details);
2174
+ const table = context?.table ?? extractTable(resultOrError.message);
2175
+ const constraint = extractConstraint(resultOrError.message);
2176
+ const kind2 = classifyKind(resultOrError.status, resultOrError.code, resultOrError.message);
2177
+ const code = toAthenaErrorCode(kind2, resultOrError.status, resultOrError.code);
2178
+ const category = toAthenaErrorCategory(kind2, resultOrError.status);
2179
+ return {
2180
+ kind: kind2,
2181
+ code,
2182
+ category,
2183
+ retryable: isRetryable(kind2, resultOrError.status),
2184
+ status: resultOrError.status,
2185
+ constraint,
2186
+ table,
2187
+ operation,
2188
+ message: resultOrError.message,
2189
+ raw: resultOrError
2190
+ };
2191
+ }
2192
+ if (resultOrError instanceof Error) {
2193
+ const maybeStatus = isRecord4(resultOrError) && typeof resultOrError.status === "number" ? resultOrError.status : void 0;
2194
+ const kind2 = classifyKind(maybeStatus, void 0, resultOrError.message);
2195
+ return {
2196
+ kind: kind2,
2197
+ code: toAthenaErrorCode(kind2, maybeStatus),
2198
+ category: toAthenaErrorCategory(kind2, maybeStatus),
2199
+ retryable: isRetryable(kind2, maybeStatus),
2200
+ status: maybeStatus,
2201
+ constraint: extractConstraint(resultOrError.message),
2202
+ table: context?.table ?? extractTable(resultOrError.message),
2203
+ operation: context?.operation,
2204
+ message: resultOrError.message,
2205
+ raw: resultOrError
2206
+ };
2207
+ }
2208
+ const message = typeof resultOrError === "string" ? resultOrError : "Unknown Athena error";
2209
+ const kind = classifyKind(void 0, void 0, message);
2210
+ return {
2211
+ kind,
2212
+ code: toAthenaErrorCode(kind, void 0),
2213
+ category: toAthenaErrorCategory(kind, void 0),
2214
+ retryable: isRetryable(kind, void 0),
2215
+ status: void 0,
2216
+ constraint: extractConstraint(message),
2217
+ table: context?.table ?? extractTable(message),
2218
+ operation: context?.operation,
2219
+ message,
2220
+ raw: resultOrError
2221
+ };
2222
+ }
2223
+ function unwrapRows(result, options) {
2224
+ if (!isOk(result)) {
2225
+ throw toAthenaGatewayError(result, "Athena request failed", options?.context);
2226
+ }
2227
+ if (result.data == null) return [];
2228
+ return Array.isArray(result.data) ? result.data : [result.data];
2229
+ }
2230
+ function unwrap(result, options) {
2231
+ if (!isOk(result)) {
2232
+ throw toAthenaGatewayError(result, "Athena request failed", options?.context);
2233
+ }
2234
+ if (result.data == null && !options?.allowNull) {
2235
+ throw toAthenaGatewayError(result, "Expected data but received null", options?.context);
2236
+ }
2237
+ return result.data;
2238
+ }
2239
+ function unwrapOne(result, options) {
2240
+ const rows = unwrapRows(result, options);
2241
+ if (!rows.length) {
2242
+ if (options?.allowNull) return null;
2243
+ throw toAthenaGatewayError(result, "Expected one row but received none", options?.context);
2244
+ }
2245
+ if (options?.requireExactlyOne && rows.length !== 1) {
2246
+ throw toAthenaGatewayError(
2247
+ result,
2248
+ `Expected exactly one row but received ${rows.length}`,
2249
+ options.context
2250
+ );
2251
+ }
2252
+ return rows[0];
2253
+ }
2254
+ function requireSuccess(result, context) {
2255
+ if (!isOk(result)) {
2256
+ throw toAthenaGatewayError(
2257
+ result,
2258
+ `Athena ${context?.operation ?? "request"} failed`,
2259
+ context
2260
+ );
2261
+ }
2262
+ return result;
2263
+ }
2264
+ function requireAffected(result, options, context) {
2265
+ requireSuccess(result, context);
2266
+ const minimum = options?.min ?? 1;
2267
+ const count = result.count;
2268
+ if (count == null) {
2269
+ throw new AthenaGatewayError({
2270
+ code: "UNKNOWN_ERROR",
2271
+ status: result.status,
2272
+ message: "Expected affected row count but response.count is missing",
2273
+ hint: 'Set call option { count: "exact" } for mutation postcondition checks.',
2274
+ cause: safeStringify(result.raw)
2275
+ });
2276
+ }
2277
+ if (count < minimum) {
2278
+ throw new AthenaGatewayError({
2279
+ code: "UNKNOWN_ERROR",
2280
+ status: result.status,
2281
+ message: `Expected at least ${minimum} affected rows but received ${count}`,
2282
+ hint: contextHint(context),
2283
+ cause: safeStringify(result.raw)
2284
+ });
2285
+ }
2286
+ return count;
2287
+ }
2288
+ function applyBounds(value, options) {
2289
+ if (options?.min !== void 0 && value < options.min) return null;
2290
+ if (options?.max !== void 0 && value > options.max) return null;
2291
+ return value;
2292
+ }
2293
+ function parseIntegerString(value) {
2294
+ const normalized = value.trim();
2295
+ if (!/^[-+]?\d+$/.test(normalized)) return null;
2296
+ const parsed = Number(normalized);
2297
+ if (!Number.isFinite(parsed) || !Number.isInteger(parsed)) return null;
2298
+ return parsed;
2299
+ }
2300
+ function coerceInt(value, options) {
2301
+ if (value == null) return null;
2302
+ if (typeof value === "number") {
2303
+ if (!Number.isFinite(value) || !Number.isInteger(value)) return null;
2304
+ return applyBounds(value, options);
2305
+ }
2306
+ if (typeof value === "string") {
2307
+ const parsed = parseIntegerString(value);
2308
+ if (parsed == null) return null;
2309
+ return applyBounds(parsed, options);
2310
+ }
2311
+ if (typeof value === "bigint") {
2312
+ if (options?.strictBigInt) {
2313
+ if (value > BigInt(Number.MAX_SAFE_INTEGER) || value < BigInt(Number.MIN_SAFE_INTEGER)) {
2314
+ return null;
2315
+ }
2316
+ }
2317
+ const parsed = Number(value);
2318
+ if (!Number.isFinite(parsed) || !Number.isInteger(parsed)) return null;
2319
+ return applyBounds(parsed, options);
2320
+ }
2321
+ return null;
2322
+ }
2323
+ function assertInt(value, label = "value", options) {
2324
+ const parsed = coerceInt(value, options);
2325
+ if (parsed == null) {
2326
+ throw new TypeError(`${label} must be a finite integer`);
2327
+ }
2328
+ return parsed;
2329
+ }
2330
+ function defaultShouldRetry(error) {
2331
+ const normalized = normalizeAthenaError(error);
2332
+ return normalized.kind === "transient" || normalized.kind === "rate_limit";
2333
+ }
2334
+ function computeDelayMs(attempt, error, config) {
2335
+ const baseDelay = config.baseDelayMs;
2336
+ const rawDelay = typeof config.backoff === "function" ? config.backoff(attempt, error) : config.backoff === "linear" ? baseDelay * attempt : baseDelay * Math.pow(2, attempt - 1);
2337
+ const safeDelay = Number.isFinite(rawDelay) ? Math.max(0, rawDelay) : 0;
2338
+ const clamped = Math.min(config.maxDelayMs, safeDelay);
2339
+ const jitterFactor = typeof config.jitter === "number" ? Math.max(0, Math.min(1, config.jitter)) : config.jitter ? 0.2 : 0;
2340
+ if (!jitterFactor) return clamped;
2341
+ const deviation = clamped * jitterFactor;
2342
+ const offset = (Math.random() * 2 - 1) * deviation;
2343
+ return Math.max(0, clamped + offset);
2344
+ }
2345
+ function sleep(ms) {
2346
+ if (ms <= 0) return Promise.resolve();
2347
+ return new Promise((resolve) => {
2348
+ setTimeout(resolve, ms);
2349
+ });
2350
+ }
2351
+ async function withRetry(config, fn) {
2352
+ const retries = Math.max(0, Math.trunc(config.retries));
2353
+ const shouldRetry = config.shouldRetry ?? defaultShouldRetry;
2354
+ const resolvedConfig = {
2355
+ baseDelayMs: config.baseDelayMs ?? 100,
2356
+ maxDelayMs: config.maxDelayMs ?? 1e4,
2357
+ backoff: config.backoff ?? "exponential",
2358
+ jitter: config.jitter ?? false
2359
+ };
2360
+ for (let attempts = 0; attempts <= retries; attempts += 1) {
2361
+ try {
2362
+ return await fn();
2363
+ } catch (error) {
2364
+ if (attempts >= retries) {
2365
+ throw error;
2366
+ }
2367
+ const currentAttempt = attempts + 1;
2368
+ const retry = await shouldRetry(error, currentAttempt);
2369
+ if (!retry) {
2370
+ throw error;
2371
+ }
2372
+ const delay = computeDelayMs(currentAttempt, error, resolvedConfig);
2373
+ await sleep(delay);
2374
+ }
2375
+ }
2376
+ throw new Error("withRetry reached an unexpected state");
2377
+ }
2378
+
2379
+ // src/db/module.ts
2380
+ function createDbModule(input) {
2381
+ const db = {
2382
+ from(table) {
2383
+ return input.from(table);
2384
+ },
2385
+ select(table, columns, options) {
2386
+ return input.from(table).select(columns, options);
2387
+ },
2388
+ insert(table, values, options) {
2389
+ return Array.isArray(values) ? input.from(table).insert(values, options) : input.from(table).insert(values, options);
2390
+ },
2391
+ upsert(table, values, options) {
2392
+ return Array.isArray(values) ? input.from(table).upsert(values, options) : input.from(table).upsert(values, options);
2393
+ },
2394
+ update(table, values, options) {
2395
+ return input.from(table).update(values, options);
2396
+ },
2397
+ delete(table, options) {
2398
+ return input.from(table).delete(options);
2399
+ },
2400
+ rpc(fn, args, options) {
2401
+ return input.rpc(fn, args, options);
2402
+ },
2403
+ query(query, options) {
2404
+ return input.query(query, options);
2405
+ }
2406
+ };
2407
+ return db;
2408
+ }
2409
+
2410
+ // src/query-ast.ts
2411
+ var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
2412
+ var FILTER_OPERATORS = /* @__PURE__ */ new Set([
2413
+ "eq",
2414
+ "neq",
2415
+ "gt",
2416
+ "gte",
2417
+ "lt",
2418
+ "lte",
2419
+ "like",
2420
+ "ilike",
2421
+ "is",
2422
+ "in",
2423
+ "contains",
2424
+ "containedBy"
2425
+ ]);
2426
+ var BOOLEAN_SAFE_OPERATORS = /* @__PURE__ */ new Set([
2427
+ "eq",
2428
+ "neq",
2429
+ "gt",
2430
+ "gte",
2431
+ "lt",
2432
+ "lte",
2433
+ "like",
2434
+ "ilike",
2435
+ "is"
2436
+ ]);
2437
+ function isRecord5(value) {
2438
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
2439
+ }
2440
+ function isUuidString(value) {
2441
+ return UUID_PATTERN.test(value.trim());
2442
+ }
2443
+ function isUuidIdentifierColumn(column) {
2444
+ return column === "id" || /(?:^|_)uuid(?:_|$)/i.test(column) || /_id$/i.test(column);
2445
+ }
2446
+ function shouldUseUuidTextComparison(column, value) {
2447
+ return typeof value === "string" && isUuidString(value) && isUuidIdentifierColumn(column);
2448
+ }
2449
+ function isRelationSelectNode(value) {
2450
+ return isRecord5(value) && isRecord5(value.select);
2451
+ }
2452
+ function normalizeIdentifier(value, label) {
2453
+ const normalized = value.trim();
2454
+ if (!normalized) {
2455
+ throw new Error(`${label} must be a non-empty string`);
2456
+ }
2457
+ return normalized;
2458
+ }
2459
+ function stringifyFilterValue(value) {
2460
+ if (Array.isArray(value)) {
2461
+ return value.join(",");
2462
+ }
2463
+ return String(value);
2464
+ }
2465
+ function buildGatewayCondition(operator, column, value) {
2466
+ const condition = { operator };
2467
+ if (column) {
2468
+ condition.column = column;
2469
+ if (operator === "eq") {
2470
+ condition.eq_column = column;
2471
+ }
2472
+ }
2473
+ if (value !== void 0) {
2474
+ condition.value = value;
2475
+ if (operator === "eq") {
2476
+ condition.eq_value = value;
2477
+ }
2478
+ }
2479
+ if (operator === "eq" && column && value !== void 0 && shouldUseUuidTextComparison(column, value)) {
2480
+ condition.column_cast = "text";
2481
+ condition.eq_column_cast = "text";
2482
+ }
2483
+ return condition;
2484
+ }
2485
+ function compileRelationToken(key, node) {
2486
+ const nested = compileSelectShape(node.select);
2487
+ const propertyKey = normalizeIdentifier(key, "select relation key");
2488
+ const relationToken = normalizeIdentifier(node.via ?? propertyKey, "select relation token");
2489
+ const alias = node.as?.trim() || (relationToken !== propertyKey ? propertyKey : "");
2490
+ const prefix = alias ? `${alias}:` : "";
2491
+ return `${prefix}${relationToken}(${nested})`;
2492
+ }
2493
+ function compileSelectShape(select) {
2494
+ if (!isRecord5(select)) {
2495
+ throw new Error("findMany select must be an object");
2496
+ }
2497
+ const tokens = [];
2498
+ for (const [rawKey, rawValue] of Object.entries(select)) {
2499
+ if (rawValue === void 0) {
2500
+ continue;
2501
+ }
2502
+ if (rawValue === true) {
2503
+ tokens.push(normalizeIdentifier(rawKey, "select column"));
2504
+ continue;
2505
+ }
2506
+ if (isRelationSelectNode(rawValue)) {
2507
+ tokens.push(compileRelationToken(rawKey, rawValue));
2508
+ continue;
2509
+ }
2510
+ throw new Error(`Unsupported select node for "${rawKey}"`);
2511
+ }
2512
+ if (tokens.length === 0) {
2513
+ throw new Error("findMany select requires at least one field");
2514
+ }
2515
+ return tokens.join(",");
2516
+ }
2517
+ function compileColumnWhere(column, input) {
2518
+ const normalizedColumn = normalizeIdentifier(column, "where column");
2519
+ if (!isRecord5(input)) {
2520
+ return [buildGatewayCondition("eq", normalizedColumn, input)];
2521
+ }
2522
+ const conditions = [];
2523
+ for (const [rawOperator, rawValue] of Object.entries(input)) {
2524
+ if (rawValue === void 0) {
2525
+ continue;
2526
+ }
2527
+ if (!FILTER_OPERATORS.has(rawOperator)) {
2528
+ throw new Error(`Unsupported where operator "${rawOperator}" on "${normalizedColumn}"`);
2529
+ }
2530
+ if ((rawOperator === "in" || rawOperator === "contains" || rawOperator === "containedBy") && !Array.isArray(rawValue)) {
2531
+ throw new Error(`where.${normalizedColumn}.${rawOperator} requires an array value`);
2532
+ }
2533
+ conditions.push(
2534
+ buildGatewayCondition(
2535
+ rawOperator,
2536
+ normalizedColumn,
2537
+ rawValue
2538
+ )
2539
+ );
2540
+ }
2541
+ if (conditions.length === 0) {
2542
+ throw new Error(`where.${normalizedColumn} requires at least one operator`);
2543
+ }
2544
+ return conditions;
2545
+ }
2546
+ function compileBooleanExpressionTerms(clause, label) {
2547
+ if (!isRecord5(clause)) {
2548
+ throw new Error(`findMany where.${label} clauses must be objects`);
2549
+ }
2550
+ const entries = Object.entries(clause).filter(([, value]) => value !== void 0);
2551
+ if (entries.length !== 1) {
2552
+ throw new Error(`findMany where.${label} clauses must target exactly one column`);
2553
+ }
2554
+ const [rawColumn, rawValue] = entries[0];
2555
+ const column = normalizeIdentifier(rawColumn, `where.${label} column`);
2556
+ if (!isRecord5(rawValue)) {
2557
+ return [`${column}.eq.${stringifyFilterValue(rawValue)}`];
2558
+ }
2559
+ const operatorEntries = Object.entries(rawValue).filter(([, value]) => value !== void 0);
2560
+ if (operatorEntries.length === 0) {
2561
+ throw new Error(`findMany where.${label}.${column} requires at least one operator`);
2562
+ }
2563
+ if (label === "not" && operatorEntries.length > 1) {
2564
+ throw new Error("findMany where.not only supports a single lossless operator expression");
2565
+ }
2566
+ return operatorEntries.map(([rawOperator, rawOperand]) => {
2567
+ if (!BOOLEAN_SAFE_OPERATORS.has(rawOperator)) {
2568
+ throw new Error(`findMany where.${label} only supports lossless scalar operators`);
2569
+ }
2570
+ if (Array.isArray(rawOperand)) {
2571
+ throw new Error(`findMany where.${label} does not support array-valued operators`);
2572
+ }
2573
+ return `${column}.${rawOperator}.${stringifyFilterValue(rawOperand)}`;
2574
+ });
2575
+ }
2576
+ function compileWhere(where) {
2577
+ if (where === void 0) {
2578
+ return void 0;
2579
+ }
2580
+ if (!isRecord5(where)) {
2581
+ throw new Error("findMany where must be an object");
2582
+ }
2583
+ const conditions = [];
2584
+ for (const [rawKey, rawValue] of Object.entries(where)) {
2585
+ if (rawValue === void 0) {
2586
+ continue;
2587
+ }
2588
+ if (rawKey === "or") {
2589
+ if (!Array.isArray(rawValue) || rawValue.length === 0) {
2590
+ throw new Error("findMany where.or must be a non-empty array");
2591
+ }
2592
+ const expressions = rawValue.flatMap(
2593
+ (value) => compileBooleanExpressionTerms(value, "or")
2594
+ );
2595
+ conditions.push(buildGatewayCondition("or", void 0, expressions.join(",")));
2596
+ continue;
2597
+ }
2598
+ if (rawKey === "not") {
2599
+ const expressions = compileBooleanExpressionTerms(rawValue, "not");
2600
+ if (expressions.length !== 1) {
2601
+ throw new Error("findMany where.not must compile to exactly one lossless expression");
2602
+ }
2603
+ conditions.push(buildGatewayCondition("not", void 0, expressions[0]));
2604
+ continue;
2605
+ }
2606
+ conditions.push(...compileColumnWhere(rawKey, rawValue));
2607
+ }
2608
+ return conditions.length > 0 ? conditions : void 0;
2609
+ }
2610
+ function resolveOrderDirection(input) {
2611
+ if (typeof input === "boolean") {
2612
+ return input === false ? "descending" : "ascending";
2613
+ }
2614
+ if (typeof input === "string") {
2615
+ const normalized = input.trim().toLowerCase();
2616
+ if (normalized === "asc" || normalized === "ascending") {
2617
+ return "ascending";
2618
+ }
2619
+ if (normalized === "desc" || normalized === "descending") {
2620
+ return "descending";
2621
+ }
2622
+ throw new Error(`Unsupported orderBy direction "${input}"`);
2623
+ }
2624
+ return input.ascending === false ? "descending" : "ascending";
2625
+ }
2626
+ function compileOrderBy(orderBy) {
2627
+ if (orderBy === void 0) {
2628
+ return void 0;
2629
+ }
2630
+ if (!isRecord5(orderBy)) {
2631
+ throw new Error("findMany orderBy must be an object");
2632
+ }
2633
+ if ("column" in orderBy) {
2634
+ return {
2635
+ field: normalizeIdentifier(String(orderBy.column), "orderBy column"),
2636
+ direction: orderBy.ascending === false ? "descending" : "ascending"
2637
+ };
2638
+ }
2639
+ const entries = Object.entries(orderBy).filter(([, value]) => value !== void 0);
2640
+ if (entries.length === 0) {
2641
+ return void 0;
2642
+ }
2643
+ if (entries.length > 1) {
2644
+ throw new Error("findMany orderBy only supports a single column in v1");
2645
+ }
2646
+ const [column, input] = entries[0];
2647
+ return {
2648
+ field: normalizeIdentifier(column, "orderBy column"),
2649
+ direction: resolveOrderDirection(input)
2650
+ };
2651
+ }
2652
+
2653
+ // src/client.ts
2654
+ var DEFAULT_COLUMNS = "*";
2655
+ var SAFE_CAST_PATTERN = /^[a-z_][a-z0-9_]*(?:\[\])?$/i;
2656
+ var ATHENA_NORMALIZED_ERROR_KEY = "__athenaNormalizedError";
2657
+ var QUERY_TRACE_STACK_SKIP_PATTERNS = [
2658
+ "src\\client.ts",
2659
+ "src/client.ts",
2660
+ "dist\\client.",
2661
+ "dist/client.",
2662
+ "node_modules\\@xylex-group\\athena",
2663
+ "node_modules/@xylex-group/athena",
2664
+ "node:internal",
2665
+ "internal/process"
2666
+ ];
2667
+ function canUseFindManyAstTransport(state) {
2668
+ return state.conditions.length === 0 && state.offset === void 0 && state.currentPage === void 0 && state.pageSize === void 0 && state.totalPages === void 0;
2669
+ }
2670
+ function toFindManyAstOrder(order) {
2671
+ if (!order) {
2672
+ return void 0;
2673
+ }
2674
+ return {
2675
+ column: order.field,
2676
+ ascending: order.direction !== "descending"
2677
+ };
2678
+ }
2679
+ function formatResult(response) {
2680
+ const result = {
2681
+ data: response.data ?? null,
2682
+ error: null,
2683
+ errorDetails: response.errorDetails ?? null,
2684
+ status: response.status,
2685
+ statusText: response.statusText ?? null,
2686
+ raw: response.raw
2687
+ };
2688
+ if (response.count !== void 0) {
2689
+ result.count = response.count;
2690
+ }
2691
+ return result;
2692
+ }
2693
+ function attachNormalizedError(result, normalizedError) {
2694
+ Object.defineProperty(result, ATHENA_NORMALIZED_ERROR_KEY, {
2695
+ value: normalizedError,
2696
+ enumerable: false,
2697
+ configurable: true,
2698
+ writable: false
2699
+ });
2700
+ }
2701
+ function createResultFormatter(experimental) {
2702
+ return (response, context) => {
2703
+ const result = formatResult(response);
2704
+ if (response.error == null && response.errorDetails == null) {
2705
+ return result;
2706
+ }
2707
+ const normalizedError = normalizeAthenaError(
2708
+ {
2709
+ ...result,
2710
+ error: response.error ?? response.errorDetails?.message ?? null
2711
+ },
2712
+ context
2713
+ );
2714
+ result.error = createResultError(response, result, normalizedError);
2715
+ attachNormalizedError(result, normalizedError);
2716
+ return result;
2717
+ };
2718
+ }
2719
+ function isRecord6(value) {
2720
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
2721
+ }
2722
+ function firstNonEmptyString2(...values) {
2723
+ for (const value of values) {
2724
+ if (typeof value === "string" && value.trim().length > 0) {
2725
+ return value.trim();
2726
+ }
2727
+ }
2728
+ return void 0;
2729
+ }
2730
+ function resolveStructuredErrorPayload2(raw) {
2731
+ if (!isRecord6(raw)) return null;
2732
+ return isRecord6(raw.error) ? raw.error : raw;
2733
+ }
2734
+ function resolveStructuredErrorDetails(payload, message) {
2735
+ if (!payload || !("details" in payload)) {
2736
+ return null;
2737
+ }
2738
+ const details = payload.details;
2739
+ if (details == null) {
2740
+ return null;
2741
+ }
2742
+ if (typeof details === "string" && details.trim() === message.trim()) {
2743
+ return null;
2744
+ }
2745
+ return details;
2746
+ }
2747
+ function createResultError(response, result, normalized) {
2748
+ const rawRecord = isRecord6(response.raw) ? response.raw : null;
2749
+ const payload = resolveStructuredErrorPayload2(response.raw);
2750
+ const message = firstNonEmptyString2(
2751
+ response.error,
2752
+ payload?.message,
2753
+ payload?.error,
2754
+ payload?.details,
2755
+ response.errorDetails?.message,
2756
+ normalized.message
2757
+ ) ?? normalized.message;
2758
+ const statusText = firstNonEmptyString2(response.statusText, rawRecord?.statusText) ?? null;
2759
+ const hint = firstNonEmptyString2(payload?.hint, response.errorDetails?.hint) ?? null;
2760
+ const code = firstNonEmptyString2(payload?.code) ?? normalized.code;
2761
+ const details = resolveStructuredErrorDetails(payload, message) ?? response.errorDetails?.cause ?? null;
2762
+ return {
2763
+ message,
2764
+ code,
2765
+ athenaCode: normalized.code,
2766
+ gatewayCode: response.errorDetails?.code ?? null,
2767
+ kind: normalized.kind,
2768
+ category: normalized.category,
2769
+ retryable: normalized.retryable,
2770
+ details,
2771
+ hint,
2772
+ status: result.status,
2773
+ statusText,
2774
+ constraint: normalized.constraint,
2775
+ table: normalized.table,
2776
+ operation: normalized.operation,
2777
+ endpoint: response.errorDetails?.endpoint,
2778
+ method: response.errorDetails?.method,
2779
+ requestId: response.errorDetails?.requestId,
2780
+ cause: response.errorDetails?.cause,
2781
+ raw: result.raw
2782
+ };
2783
+ }
2784
+ function parseQueryTraceCallsiteFrame(frame) {
2785
+ const trimmed = frame.trim();
2786
+ if (!trimmed) {
2787
+ return null;
2788
+ }
2789
+ let body = trimmed.replace(/^at\s+/, "");
2790
+ if (body.startsWith("async ")) {
2791
+ body = body.slice(6);
2792
+ }
2793
+ let functionName;
2794
+ let location = body;
2795
+ const wrappedMatch = body.match(/^(.*?)\s+\((.*)\)$/);
2796
+ if (wrappedMatch) {
2797
+ functionName = wrappedMatch[1].trim() || void 0;
2798
+ location = wrappedMatch[2].trim();
2799
+ }
2800
+ const locationMatch = location.match(/^(.*):(\d+):(\d+)$/);
2801
+ if (!locationMatch) {
2802
+ return null;
2803
+ }
2804
+ const filePath = locationMatch[1].replace(/^file:\/\//, "");
2805
+ const line = Number(locationMatch[2]);
2806
+ const column = Number(locationMatch[3]);
2807
+ if (!Number.isFinite(line) || !Number.isFinite(column)) {
2808
+ return null;
2809
+ }
2810
+ const normalizedPath = filePath.replace(/\\/g, "/");
2811
+ const fileName = normalizedPath.split("/").at(-1) ?? filePath;
2812
+ return {
2813
+ filePath,
2814
+ fileName,
2815
+ line,
2816
+ column,
2817
+ frame: trimmed,
2818
+ functionName
2819
+ };
2820
+ }
2821
+ function captureQueryTraceCallsite() {
2822
+ const stack = new Error().stack;
2823
+ if (!stack) return null;
2824
+ const frames = stack.split("\n").slice(2).map((frame) => frame.trim()).filter(Boolean);
2825
+ for (const frame of frames) {
2826
+ if (QUERY_TRACE_STACK_SKIP_PATTERNS.some((pattern) => frame.includes(pattern))) {
2827
+ continue;
2828
+ }
2829
+ const callsite = parseQueryTraceCallsiteFrame(frame);
2830
+ if (callsite) return callsite;
2831
+ }
2832
+ const fallback = frames.find((frame) => !frame.includes("captureQueryTraceCallsite"));
2833
+ return fallback ? parseQueryTraceCallsiteFrame(fallback) : null;
2834
+ }
2835
+ function defaultQueryTraceLogger(event) {
2836
+ const target = event.table ?? event.functionName ?? "gateway";
2837
+ const outcomeState = event.outcome?.error ? "error" : "ok";
2838
+ const banner = `[athena-js][trace] ${event.operation.toUpperCase()} ${event.endpoint} ${target} ${event.durationMs}ms ${outcomeState}`;
2839
+ console.info(banner, event);
2840
+ }
2841
+ function captureTraceCallsite(tracer) {
2842
+ return tracer?.captureCallsite() ?? null;
2843
+ }
2844
+ function createTraceCallsiteStore(tracer, initialCallsite) {
2845
+ let storedCallsite = initialCallsite ?? void 0;
2846
+ return {
2847
+ resolve(callsite) {
2848
+ if (callsite) {
2849
+ storedCallsite = callsite;
2850
+ return callsite;
2851
+ }
2852
+ if (storedCallsite !== void 0) {
2853
+ return storedCallsite;
2854
+ }
2855
+ const capturedCallsite = captureTraceCallsite(tracer);
2856
+ if (capturedCallsite) {
2857
+ storedCallsite = capturedCallsite;
2858
+ }
2859
+ return capturedCallsite;
2860
+ }
2861
+ };
2862
+ }
2863
+ function createQueryTracer(experimental) {
2864
+ const traceOption = experimental?.traceQueries;
2865
+ if (!traceOption) {
2866
+ return void 0;
2867
+ }
2868
+ const logger = typeof traceOption === "object" && traceOption.logger ? traceOption.logger : defaultQueryTraceLogger;
2869
+ const emit = (event) => {
2870
+ try {
2871
+ logger(event);
2872
+ } catch (error) {
2873
+ console.warn("[athena-js][trace] logger failed", error);
2874
+ }
2875
+ };
2876
+ return {
2877
+ captureCallsite: captureQueryTraceCallsite,
2878
+ publishSuccess(context, result, durationMs, callsite) {
2879
+ emit({
2880
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2881
+ durationMs,
2882
+ operation: context.operation,
2883
+ endpoint: context.endpoint,
2884
+ table: context.table,
2885
+ functionName: context.functionName,
2886
+ sql: context.sql,
2887
+ payload: context.payload,
2888
+ options: context.options,
2889
+ callsite,
2890
+ outcome: {
2891
+ status: result.status,
2892
+ error: result.error,
2893
+ errorDetails: result.errorDetails ?? null,
2894
+ count: result.count ?? null,
2895
+ data: result.data,
2896
+ raw: result.raw
2897
+ }
2898
+ });
2899
+ },
2900
+ publishFailure(context, error, durationMs, callsite) {
2901
+ emit({
2902
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2903
+ durationMs,
2904
+ operation: context.operation,
2905
+ endpoint: context.endpoint,
2906
+ table: context.table,
2907
+ functionName: context.functionName,
2908
+ sql: context.sql,
2909
+ payload: context.payload,
2910
+ options: context.options,
2911
+ callsite,
2912
+ thrownError: error
2913
+ });
2914
+ }
2915
+ };
2916
+ }
2917
+ async function executeWithQueryTrace(tracer, context, runner, callsiteOverride) {
2918
+ if (!tracer) {
2919
+ return runner();
2920
+ }
2921
+ const callsite = callsiteOverride ?? tracer.captureCallsite();
2922
+ const startedAt = Date.now();
2923
+ try {
2924
+ const result = await runner();
2925
+ tracer.publishSuccess(context, result, Date.now() - startedAt, callsite);
2926
+ return result;
2927
+ } catch (error) {
2928
+ tracer.publishFailure(context, error, Date.now() - startedAt, callsite);
2929
+ throw error;
2930
+ }
2931
+ }
2932
+ function toSingleResult(response) {
2933
+ const payload = response.data;
2934
+ const singleData = Array.isArray(payload) ? payload.length ? payload[0] : null : payload ?? null;
2935
+ return {
2936
+ ...response,
2937
+ data: singleData
2938
+ };
2939
+ }
2940
+ function mergeOptions(...options) {
2941
+ return options.reduce((acc, next) => {
2942
+ if (!next) return acc;
2943
+ return { ...acc, ...next };
2944
+ }, void 0);
2945
+ }
2946
+ function asAthenaJsonObject(value) {
2947
+ return value;
2948
+ }
2949
+ function asAthenaJsonObjectArray(values) {
2950
+ return values;
2951
+ }
2952
+ function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS, tracer, initialCallsite) {
2953
+ let selectedColumns = defaultColumns === null ? void 0 : defaultColumns;
2954
+ let selectedOptions;
2955
+ let promise = null;
2956
+ const callsiteStore = createTraceCallsiteStore(tracer, initialCallsite);
2957
+ const run = (columns, options, callsite) => {
2958
+ const payloadColumns = columns ?? selectedColumns;
2959
+ const payloadOptions = options ?? selectedOptions;
2960
+ if (!promise) {
2961
+ promise = executor(payloadColumns, payloadOptions, callsiteStore.resolve(callsite));
2962
+ }
2963
+ return promise;
2964
+ };
2965
+ const mutationQuery = {
2966
+ select(columns = selectedColumns, options) {
2967
+ selectedColumns = columns;
2968
+ selectedOptions = options ?? selectedOptions;
2969
+ return run(columns, options, captureTraceCallsite(tracer));
2970
+ },
2971
+ returning(columns = selectedColumns, options) {
2972
+ return mutationQuery.select(columns, options);
2973
+ },
2974
+ single(columns = selectedColumns, options) {
2975
+ selectedColumns = columns;
2976
+ selectedOptions = options ?? selectedOptions;
2977
+ return run(columns, options, captureTraceCallsite(tracer)).then(toSingleResult);
2978
+ },
2979
+ maybeSingle(columns = selectedColumns, options) {
2980
+ return mutationQuery.single(columns, options);
2981
+ },
2982
+ then(onfulfilled, onrejected) {
2983
+ return run(selectedColumns, selectedOptions).then(onfulfilled, onrejected);
2984
+ },
2985
+ catch(onrejected) {
2986
+ return run(selectedColumns, selectedOptions).catch(onrejected);
2987
+ },
2988
+ finally(onfinally) {
2989
+ return run(selectedColumns, selectedOptions).finally(onfinally);
2990
+ }
2991
+ };
2992
+ return mutationQuery;
2993
+ }
2994
+ function getResourceId(state) {
2995
+ const candidate = state.conditions.find(
2996
+ (condition) => condition.operator === "eq" && (condition.column === "resource_id" || condition.column === "id")
2997
+ );
2998
+ return candidate?.value?.toString();
2999
+ }
3000
+ function stringifyFilterValue2(value) {
3001
+ if (Array.isArray(value)) {
3002
+ return value.join(",");
3003
+ }
3004
+ return String(value);
3005
+ }
3006
+ function normalizeCast(cast) {
3007
+ const normalized = cast.trim().toLowerCase();
3008
+ if (!SAFE_CAST_PATTERN.test(normalized)) {
3009
+ throw new Error(`Invalid cast type "${cast}"`);
3010
+ }
3011
+ return normalized;
3012
+ }
3013
+ function escapeSqlStringLiteral(value) {
3014
+ return value.replace(/'/g, "''");
3015
+ }
3016
+ function toSqlLiteral(value) {
3017
+ if (value === null) return "NULL";
3018
+ if (typeof value === "number") return Number.isFinite(value) ? String(value) : "NULL";
3019
+ if (typeof value === "boolean") return value ? "TRUE" : "FALSE";
3020
+ return `'${escapeSqlStringLiteral(value)}'`;
3021
+ }
3022
+ function withCast(expression, cast) {
3023
+ if (!cast) return expression;
3024
+ return `${expression}::${normalizeCast(cast)}`;
3025
+ }
3026
+ function buildSelectColumnsClause(columns) {
3027
+ if (Array.isArray(columns)) {
3028
+ return columns.map((column) => quoteSelectColumnToken(column)).join(", ");
3029
+ }
3030
+ return quoteSelectColumnsExpression(columns);
3031
+ }
3032
+ function parseIdentifierSegment(input) {
3033
+ const trimmed = input.trim();
3034
+ if (!trimmed) return null;
3035
+ if (!trimmed.startsWith('"')) {
3036
+ return {
3037
+ normalizedValue: trimmed.toLowerCase()
3038
+ };
3039
+ }
3040
+ let value = "";
3041
+ let index = 1;
3042
+ let closed = false;
3043
+ while (index < trimmed.length) {
3044
+ const char = trimmed[index];
3045
+ const next = index + 1 < trimmed.length ? trimmed[index + 1] : "";
3046
+ if (char === '"' && next === '"') {
3047
+ value += '"';
3048
+ index += 2;
3049
+ continue;
3050
+ }
3051
+ if (char === '"') {
3052
+ closed = true;
3053
+ index += 1;
3054
+ break;
3055
+ }
3056
+ value += char;
3057
+ index += 1;
3058
+ }
3059
+ if (!closed || trimmed.slice(index).trim().length > 0 || !value.trim()) {
3060
+ return null;
3061
+ }
3062
+ return {
3063
+ normalizedValue: value
3064
+ };
3065
+ }
3066
+ function splitQualifiedTableName(tableName) {
3067
+ const trimmed = tableName.trim();
3068
+ let inQuotes = false;
3069
+ for (let index = 0; index < trimmed.length; index += 1) {
3070
+ const char = trimmed[index];
3071
+ const next = index + 1 < trimmed.length ? trimmed[index + 1] : "";
3072
+ if (char === '"') {
3073
+ if (inQuotes && next === '"') {
3074
+ index += 1;
3075
+ continue;
3076
+ }
3077
+ inQuotes = !inQuotes;
3078
+ continue;
3079
+ }
3080
+ if (char === "." && !inQuotes) {
3081
+ const schemaSegment = trimmed.slice(0, index).trim();
3082
+ const tableSegment = trimmed.slice(index + 1).trim();
3083
+ if (!schemaSegment || !tableSegment) {
3084
+ return null;
3085
+ }
3086
+ return { schemaSegment };
3087
+ }
3088
+ }
3089
+ return null;
3090
+ }
3091
+ function resolveTableNameForCall(tableName, schema) {
3092
+ if (!schema) return tableName;
3093
+ const normalizedSchema = schema.trim();
3094
+ if (!normalizedSchema) {
3095
+ throw new Error("schema option must be a non-empty string");
3096
+ }
3097
+ const normalizedTableName = tableName.trim();
3098
+ const parsedSchema = parseIdentifierSegment(normalizedSchema);
3099
+ if (!parsedSchema) {
3100
+ throw new Error("schema option must be a non-empty string");
3101
+ }
3102
+ const qualified = splitQualifiedTableName(normalizedTableName);
3103
+ if (qualified) {
3104
+ const parsedTableSchema = parseIdentifierSegment(qualified.schemaSegment);
3105
+ const sameSchema = parsedTableSchema ? parsedTableSchema.normalizedValue === parsedSchema.normalizedValue : normalizedTableName.startsWith(`${normalizedSchema}.`);
3106
+ if (sameSchema) {
3107
+ return normalizedTableName;
3108
+ }
3109
+ throw new Error(
3110
+ `schema option "${normalizedSchema}" conflicts with schema-qualified table "${normalizedTableName}"`
3111
+ );
3112
+ }
3113
+ return `${normalizedSchema}.${normalizedTableName}`;
3114
+ }
3115
+ function conditionToSqlClause(condition) {
3116
+ if (!condition.column) return null;
3117
+ const column = withCast(quoteQualifiedIdentifier(condition.column), condition.column_cast);
3118
+ const value = condition.value;
3119
+ const sqlOperator = {
3120
+ eq: "=",
3121
+ neq: "!=",
3122
+ gt: ">",
3123
+ gte: ">=",
3124
+ lt: "<",
3125
+ lte: "<=",
3126
+ like: "LIKE",
3127
+ ilike: "ILIKE"
3128
+ };
3129
+ switch (condition.operator) {
3130
+ case "eq":
3131
+ case "neq":
3132
+ case "gt":
3133
+ case "gte":
3134
+ case "lt":
3135
+ case "lte":
3136
+ case "like":
3137
+ case "ilike": {
3138
+ if (Array.isArray(value) || value === void 0) return null;
3139
+ const rhs = withCast(toSqlLiteral(value), condition.value_cast);
3140
+ return `${column} ${sqlOperator[condition.operator]} ${rhs}`;
3141
+ }
3142
+ case "is": {
3143
+ if (value === null) return `${column} IS NULL`;
3144
+ if (value === true) return `${column} IS TRUE`;
3145
+ if (value === false) return `${column} IS FALSE`;
3146
+ return null;
3147
+ }
3148
+ case "in": {
3149
+ if (!Array.isArray(value)) return null;
3150
+ if (value.length === 0) return "FALSE";
3151
+ const values = value.map((item) => withCast(toSqlLiteral(item), condition.value_cast));
3152
+ return `${column} IN (${values.join(", ")})`;
3153
+ }
3154
+ default:
3155
+ return null;
3156
+ }
3157
+ }
3158
+ function buildTypedSelectQuery(input) {
3159
+ const whereClauses = [];
3160
+ for (const condition of input.conditions) {
3161
+ const clause = conditionToSqlClause(condition);
3162
+ if (!clause) return null;
3163
+ whereClauses.push(clause);
3164
+ }
3165
+ let limit = input.limit;
3166
+ let offset = input.offset;
3167
+ if (limit === void 0 && input.pageSize !== void 0) {
3168
+ limit = input.pageSize;
3169
+ }
3170
+ if (offset === void 0 && input.pageSize !== void 0 && input.currentPage !== void 0 && input.currentPage > 0) {
3171
+ offset = (input.currentPage - 1) * input.pageSize;
3172
+ }
3173
+ const sqlParts = [
3174
+ `SELECT ${buildSelectColumnsClause(input.columns)} FROM ${quoteQualifiedIdentifier(input.tableName)}`
3175
+ ];
3176
+ if (whereClauses.length > 0) {
3177
+ sqlParts.push(`WHERE ${whereClauses.join(" AND ")}`);
3178
+ }
3179
+ if (input.order?.field) {
3180
+ const direction = input.order.direction === "descending" ? "DESC" : "ASC";
3181
+ sqlParts.push(`ORDER BY ${quoteQualifiedIdentifier(input.order.field)} ${direction}`);
3182
+ }
3183
+ if (limit !== void 0) {
3184
+ sqlParts.push(`LIMIT ${Math.max(0, Math.trunc(limit))}`);
3185
+ }
3186
+ if (offset !== void 0) {
3187
+ sqlParts.push(`OFFSET ${Math.max(0, Math.trunc(offset))}`);
3188
+ }
3189
+ return `${sqlParts.join(" ")};`;
3190
+ }
3191
+ function sanitizeSqlComment(comment) {
3192
+ return comment.replace(/\*\//g, "* /");
3193
+ }
3194
+ function toSqlJsonLiteral(value) {
3195
+ if (value === void 0) return "DEFAULT";
3196
+ if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
3197
+ return toSqlLiteral(value);
3198
+ }
3199
+ return `'${escapeSqlStringLiteral(JSON.stringify(value))}'::jsonb`;
3200
+ }
3201
+ function conditionToDebugSqlClause(condition) {
3202
+ const exact = conditionToSqlClause(condition);
3203
+ if (exact) return exact;
3204
+ const rawCondition = sanitizeSqlComment(JSON.stringify(condition));
3205
+ if (!condition.column) {
3206
+ return `TRUE /* unsupported condition: ${rawCondition} */`;
3207
+ }
3208
+ const column = withCast(quoteQualifiedIdentifier(condition.column), condition.column_cast);
3209
+ const value = condition.value;
3210
+ const rhs = withCast(toSqlJsonLiteral(value), condition.value_cast);
3211
+ switch (condition.operator) {
3212
+ case "contains":
3213
+ return `${column} @> ${rhs}`;
3214
+ case "containedBy":
3215
+ return `${column} <@ ${rhs}`;
3216
+ case "not":
3217
+ return `TRUE /* NOT expression passthrough: ${rawCondition} */`;
3218
+ case "or":
3219
+ return `TRUE /* OR expression passthrough: ${rawCondition} */`;
3220
+ default:
3221
+ return `TRUE /* unsupported condition: ${rawCondition} */`;
3222
+ }
3223
+ }
3224
+ function resolvePagination(input) {
3225
+ let limit = input.limit;
3226
+ let offset = input.offset;
3227
+ if (limit === void 0 && input.pageSize !== void 0) {
3228
+ limit = input.pageSize;
3229
+ }
3230
+ if (offset === void 0 && input.pageSize !== void 0 && input.currentPage !== void 0 && input.currentPage > 0) {
3231
+ offset = (input.currentPage - 1) * input.pageSize;
3232
+ }
3233
+ return { limit, offset };
3234
+ }
3235
+ function appendOrderLimitOffset(sqlParts, order, limit, offset) {
3236
+ if (order?.field) {
3237
+ const direction = order.direction === "descending" ? "DESC" : "ASC";
3238
+ sqlParts.push(`ORDER BY ${quoteQualifiedIdentifier(order.field)} ${direction}`);
3239
+ }
3240
+ if (limit !== void 0) {
3241
+ sqlParts.push(`LIMIT ${Math.max(0, Math.trunc(limit))}`);
3242
+ }
3243
+ if (offset !== void 0) {
3244
+ sqlParts.push(`OFFSET ${Math.max(0, Math.trunc(offset))}`);
3245
+ }
3246
+ }
3247
+ function buildDebugSelectQuery(input) {
3248
+ const sqlParts = [
3249
+ `SELECT ${buildSelectColumnsClause(input.columns)} FROM ${quoteQualifiedIdentifier(input.tableName)}`
3250
+ ];
3251
+ if (input.conditions?.length) {
3252
+ const whereClauses = input.conditions.map(conditionToDebugSqlClause);
3253
+ sqlParts.push(`WHERE ${whereClauses.join(" AND ")}`);
3254
+ }
3255
+ const pagination = resolvePagination(input);
3256
+ appendOrderLimitOffset(sqlParts, input.order, pagination.limit, pagination.offset);
3257
+ return `${sqlParts.join(" ")};`;
3258
+ }
3259
+ function resolveDebugTableIdentifier(tableName) {
3260
+ if (!tableName?.trim()) {
3261
+ return '"__unknown_table__"';
3262
+ }
3263
+ return quoteQualifiedIdentifier(tableName);
3264
+ }
3265
+ function buildInsertDebugSql(payload) {
3266
+ const rows = Array.isArray(payload.insert_body) ? payload.insert_body : [payload.insert_body];
3267
+ const columns = [];
3268
+ const seen = /* @__PURE__ */ new Set();
3269
+ for (const row of rows) {
3270
+ for (const column of Object.keys(row)) {
3271
+ if (seen.has(column)) continue;
3272
+ seen.add(column);
3273
+ columns.push(column);
3274
+ }
3275
+ }
3276
+ const sqlParts = [`INSERT INTO ${quoteQualifiedIdentifier(payload.table_name)}`];
3277
+ if (!rows.length || !columns.length) {
3278
+ sqlParts.push("DEFAULT VALUES");
3279
+ if (rows.length > 1) {
3280
+ sqlParts.push(`/* trace: ${rows.length} rows collapsed to DEFAULT VALUES */`);
3281
+ }
3282
+ } else {
3283
+ const valuesClause = rows.map((row) => {
3284
+ const values = columns.map((column) => {
3285
+ const hasColumn = Object.prototype.hasOwnProperty.call(row, column);
3286
+ if (!hasColumn) {
3287
+ return payload.default_to_null ? "NULL" : "DEFAULT";
3288
+ }
3289
+ const rowValue = row[column];
3290
+ return toSqlJsonLiteral(rowValue);
3291
+ });
3292
+ return `(${values.join(", ")})`;
3293
+ }).join(", ");
3294
+ const columnClause = columns.map((column) => quoteQualifiedIdentifier(column)).join(", ");
3295
+ sqlParts.push(`(${columnClause})`);
3296
+ sqlParts.push(`VALUES ${valuesClause}`);
3297
+ }
3298
+ if (payload.on_conflict) {
3299
+ const conflictColumns = Array.isArray(payload.on_conflict) ? payload.on_conflict.map((column) => quoteQualifiedIdentifier(column)).join(", ") : payload.on_conflict;
3300
+ if (payload.update_body && Object.keys(payload.update_body).length > 0) {
3301
+ const assignments = Object.entries(payload.update_body).map(
3302
+ ([column, value]) => `${quoteQualifiedIdentifier(column)} = ${toSqlJsonLiteral(value)}`
3303
+ );
3304
+ sqlParts.push(`ON CONFLICT (${conflictColumns}) DO UPDATE SET ${assignments.join(", ")}`);
3305
+ } else {
3306
+ sqlParts.push(`ON CONFLICT (${conflictColumns}) DO NOTHING`);
3307
+ }
3308
+ }
3309
+ if (payload.columns) {
3310
+ sqlParts.push(`RETURNING ${buildSelectColumnsClause(payload.columns)}`);
3311
+ }
3312
+ return `${sqlParts.join(" ")};`;
3313
+ }
3314
+ function buildUpdateDebugSql(payload) {
3315
+ const set = payload.set ?? payload.data ?? {};
3316
+ const assignments = Object.entries(set).map(
3317
+ ([column, value]) => `${quoteQualifiedIdentifier(column)} = ${toSqlJsonLiteral(value)}`
3318
+ );
3319
+ const sqlParts = [
3320
+ `UPDATE ${resolveDebugTableIdentifier(payload.table_name)} SET ${assignments.length ? assignments.join(", ") : "/* empty set */"}`
3321
+ ];
3322
+ if (payload.conditions?.length) {
3323
+ const whereClauses = payload.conditions.map(conditionToDebugSqlClause);
3324
+ sqlParts.push(`WHERE ${whereClauses.join(" AND ")}`);
3325
+ }
3326
+ const pagination = resolvePagination({
3327
+ currentPage: payload.current_page,
3328
+ pageSize: payload.page_size
3329
+ });
3330
+ appendOrderLimitOffset(sqlParts, payload.sort_by, pagination.limit, pagination.offset);
3331
+ if (payload.columns) {
3332
+ sqlParts.push(`RETURNING ${buildSelectColumnsClause(payload.columns)}`);
3333
+ }
3334
+ return `${sqlParts.join(" ")};`;
3335
+ }
3336
+ function buildDeleteDebugSql(payload) {
3337
+ const sqlParts = [`DELETE FROM ${quoteQualifiedIdentifier(payload.table_name)}`];
3338
+ const whereClauses = [];
3339
+ if (payload.resource_id) {
3340
+ whereClauses.push(`"resource_id" = ${toSqlLiteral(payload.resource_id)}`);
3341
+ }
3342
+ if (payload.conditions?.length) {
3343
+ whereClauses.push(...payload.conditions.map(conditionToDebugSqlClause));
3344
+ }
3345
+ if (whereClauses.length) {
3346
+ sqlParts.push(`WHERE ${whereClauses.join(" AND ")}`);
3347
+ }
3348
+ const pagination = resolvePagination({
3349
+ currentPage: payload.current_page,
3350
+ pageSize: payload.page_size
3351
+ });
3352
+ appendOrderLimitOffset(sqlParts, payload.sort_by, pagination.limit, pagination.offset);
3353
+ if (payload.columns) {
3354
+ sqlParts.push(`RETURNING ${buildSelectColumnsClause(payload.columns)}`);
3355
+ }
3356
+ return `${sqlParts.join(" ")};`;
3357
+ }
3358
+ function rpcFilterToSqlClause(filter) {
3359
+ const column = quoteQualifiedIdentifier(filter.column);
3360
+ const value = filter.value;
3361
+ switch (filter.operator) {
3362
+ case "eq":
3363
+ case "neq":
3364
+ case "gt":
3365
+ case "gte":
3366
+ case "lt":
3367
+ case "lte":
3368
+ case "like":
3369
+ case "ilike": {
3370
+ if (value === void 0 || Array.isArray(value)) {
3371
+ return `TRUE /* unsupported rpc filter: ${sanitizeSqlComment(JSON.stringify(filter))} */`;
3372
+ }
3373
+ const operatorMap = {
3374
+ eq: "=",
3375
+ neq: "!=",
3376
+ gt: ">",
3377
+ gte: ">=",
3378
+ lt: "<",
3379
+ lte: "<=",
3380
+ like: "LIKE",
3381
+ ilike: "ILIKE"
3382
+ };
3383
+ return `${column} ${operatorMap[filter.operator]} ${toSqlLiteral(value)}`;
3384
+ }
3385
+ case "is":
3386
+ if (value === null) return `${column} IS NULL`;
3387
+ if (value === true) return `${column} IS TRUE`;
3388
+ if (value === false) return `${column} IS FALSE`;
3389
+ return `TRUE /* unsupported rpc filter: ${sanitizeSqlComment(JSON.stringify(filter))} */`;
3390
+ case "in":
3391
+ if (!Array.isArray(value)) {
3392
+ return `TRUE /* unsupported rpc filter: ${sanitizeSqlComment(JSON.stringify(filter))} */`;
3393
+ }
3394
+ if (value.length === 0) return "FALSE";
3395
+ return `${column} IN (${value.map((item) => toSqlLiteral(item)).join(", ")})`;
3396
+ default:
3397
+ return `TRUE /* unsupported rpc filter: ${sanitizeSqlComment(JSON.stringify(filter))} */`;
3398
+ }
3399
+ }
3400
+ function buildRpcDebugSql(payload) {
3401
+ const argsEntries = payload.args ? Object.entries(payload.args) : [];
3402
+ const argsClause = argsEntries.map(([key, value]) => `${quoteQualifiedIdentifier(key)} => ${toSqlJsonLiteral(value)}`).join(", ");
3403
+ const functionRef = payload.schema ? `${quoteQualifiedIdentifier(payload.schema)}.${quoteQualifiedIdentifier(payload.function)}` : quoteQualifiedIdentifier(payload.function);
3404
+ const sqlParts = [
3405
+ `SELECT ${payload.select ? quoteSelectColumnsExpression(payload.select) : "*"} FROM ${functionRef}(${argsClause})`
3406
+ ];
3407
+ if (payload.filters?.length) {
3408
+ sqlParts.push(`WHERE ${payload.filters.map(rpcFilterToSqlClause).join(" AND ")}`);
3409
+ }
3410
+ if (payload.order?.column) {
3411
+ const direction = payload.order.ascending === false ? "DESC" : "ASC";
3412
+ sqlParts.push(`ORDER BY ${quoteQualifiedIdentifier(payload.order.column)} ${direction}`);
3413
+ }
3414
+ if (payload.limit !== void 0) {
3415
+ sqlParts.push(`LIMIT ${Math.max(0, Math.trunc(payload.limit))}`);
3416
+ }
3417
+ if (payload.offset !== void 0) {
3418
+ sqlParts.push(`OFFSET ${Math.max(0, Math.trunc(payload.offset))}`);
3419
+ }
3420
+ return `${sqlParts.join(" ")};`;
3421
+ }
3422
+ function createFilterMethods(state, addCondition, self) {
3423
+ return {
3424
+ eq(column, value) {
3425
+ const columnName = String(column);
3426
+ if (shouldUseUuidTextComparison(columnName, value)) {
3427
+ addCondition("eq", columnName, value, { columnCast: "text" });
3428
+ } else {
3429
+ addCondition("eq", columnName, value);
3430
+ }
3431
+ return self;
3432
+ },
3433
+ eqCast(column, value, cast) {
3434
+ addCondition("eq", String(column), value, { valueCast: cast });
3435
+ return self;
3436
+ },
3437
+ eqUuid(column, value) {
3438
+ addCondition("eq", String(column), value, { valueCast: "uuid" });
3439
+ return self;
3440
+ },
3441
+ match(filters) {
3442
+ Object.entries(filters).forEach(([column, value]) => {
3443
+ if (value === void 0) {
3444
+ return;
3445
+ }
3446
+ if (shouldUseUuidTextComparison(column, value)) {
3447
+ addCondition("eq", column, value, { columnCast: "text" });
3448
+ } else {
3449
+ addCondition("eq", column, value);
3450
+ }
3451
+ });
3452
+ return self;
3453
+ },
3454
+ range(from, to) {
3455
+ state.offset = from;
3456
+ state.limit = to - from + 1;
3457
+ return self;
3458
+ },
3459
+ limit(count) {
3460
+ state.limit = count;
3461
+ return self;
3462
+ },
3463
+ offset(count) {
3464
+ state.offset = count;
3465
+ return self;
3466
+ },
3467
+ currentPage(value) {
3468
+ state.currentPage = value;
3469
+ return self;
3470
+ },
3471
+ pageSize(value) {
3472
+ state.pageSize = value;
3473
+ return self;
3474
+ },
3475
+ totalPages(value) {
3476
+ state.totalPages = value;
3477
+ return self;
3478
+ },
3479
+ order(column, options) {
3480
+ state.order = {
3481
+ field: String(column),
3482
+ direction: options?.ascending === false ? "descending" : "ascending"
3483
+ };
3484
+ return self;
3485
+ },
3486
+ gt(column, value) {
3487
+ addCondition("gt", String(column), value);
3488
+ return self;
3489
+ },
3490
+ gte(column, value) {
3491
+ addCondition("gte", String(column), value);
3492
+ return self;
3493
+ },
3494
+ lt(column, value) {
3495
+ addCondition("lt", String(column), value);
3496
+ return self;
3497
+ },
3498
+ lte(column, value) {
3499
+ addCondition("lte", String(column), value);
3500
+ return self;
3501
+ },
3502
+ neq(column, value) {
3503
+ addCondition("neq", String(column), value);
3504
+ return self;
3505
+ },
3506
+ like(column, value) {
3507
+ addCondition("like", String(column), value);
3508
+ return self;
3509
+ },
3510
+ ilike(column, value) {
3511
+ addCondition("ilike", String(column), value);
3512
+ return self;
3513
+ },
3514
+ is(column, value) {
3515
+ addCondition("is", String(column), value);
3516
+ return self;
3517
+ },
3518
+ in(column, values) {
3519
+ addCondition("in", String(column), values);
3520
+ return self;
3521
+ },
3522
+ contains(column, values) {
3523
+ addCondition("contains", String(column), values);
3524
+ return self;
3525
+ },
3526
+ containedBy(column, values) {
3527
+ addCondition("containedBy", String(column), values);
3528
+ return self;
3529
+ },
3530
+ not(columnOrExpression, operator, value) {
3531
+ const expression = String(columnOrExpression);
3532
+ if (operator != null && value !== void 0) {
3533
+ addCondition("not", void 0, `${expression}.${operator}.${stringifyFilterValue2(value)}`);
3534
+ } else {
3535
+ addCondition("not", void 0, expression);
3536
+ }
3537
+ return self;
3538
+ },
3539
+ or(expression) {
3540
+ addCondition("or", void 0, expression);
3541
+ return self;
3542
+ }
3543
+ };
3544
+ }
3545
+ function toRpcSelect(columns) {
3546
+ if (!columns) return void 0;
3547
+ return Array.isArray(columns) ? columns.join(",") : columns;
3548
+ }
3549
+ function createRpcFilterMethods(filters, self) {
3550
+ const addFilter = (operator, column, value) => {
3551
+ filters.push({ column, operator, value });
3552
+ };
3553
+ return {
3554
+ eq(column, value) {
3555
+ addFilter("eq", column, value);
3556
+ return self;
3557
+ },
3558
+ neq(column, value) {
3559
+ addFilter("neq", column, value);
3560
+ return self;
3561
+ },
3562
+ gt(column, value) {
3563
+ addFilter("gt", column, value);
3564
+ return self;
3565
+ },
3566
+ gte(column, value) {
3567
+ addFilter("gte", column, value);
3568
+ return self;
3569
+ },
3570
+ lt(column, value) {
3571
+ addFilter("lt", column, value);
3572
+ return self;
3573
+ },
3574
+ lte(column, value) {
3575
+ addFilter("lte", column, value);
3576
+ return self;
3577
+ },
3578
+ like(column, value) {
3579
+ addFilter("like", column, value);
3580
+ return self;
3581
+ },
3582
+ ilike(column, value) {
3583
+ addFilter("ilike", column, value);
3584
+ return self;
3585
+ },
3586
+ is(column, value) {
3587
+ addFilter("is", column, value);
3588
+ return self;
3589
+ },
3590
+ in(column, values) {
3591
+ addFilter("in", column, values);
3592
+ return self;
3593
+ }
3594
+ };
3595
+ }
3596
+ function createRpcBuilder(functionName, args, baseOptions, client, formatGatewayResult, tracer, initialCallsite) {
3597
+ const state = {
3598
+ filters: []
3599
+ };
3600
+ let selectedColumns;
3601
+ let selectedOptions;
3602
+ let promise = null;
3603
+ const callsiteStore = createTraceCallsiteStore(tracer, initialCallsite);
3604
+ const executeRpc = async (columns, options, callsite) => {
3605
+ const mergedOptions = mergeOptions(baseOptions, options);
3606
+ const payload = {
3607
+ function: functionName,
3608
+ args,
3609
+ schema: mergedOptions?.schema,
3610
+ select: toRpcSelect(columns),
3611
+ filters: state.filters.length ? [...state.filters] : void 0,
3612
+ count: mergedOptions?.count,
3613
+ head: mergedOptions?.head,
3614
+ limit: state.limit,
3615
+ offset: state.offset,
3616
+ order: state.order
3617
+ };
3618
+ const endpoint = mergedOptions?.get ? `/rpc/${functionName}` : "/gateway/rpc";
3619
+ const sql = buildRpcDebugSql(payload);
3620
+ return executeWithQueryTrace(
3621
+ tracer,
3622
+ {
3623
+ operation: "rpc",
3624
+ endpoint,
3625
+ functionName,
3626
+ sql,
3627
+ payload,
3628
+ options: mergedOptions
3629
+ },
3630
+ async () => {
3631
+ const response = await client.rpcGateway(payload, mergedOptions);
3632
+ return formatGatewayResult(response, { operation: "rpc" });
3633
+ },
3634
+ callsite
3635
+ );
3636
+ };
3637
+ const run = (columns, options, callsite) => {
3638
+ const payloadColumns = columns ?? selectedColumns;
3639
+ const payloadOptions = options ?? selectedOptions;
3640
+ if (!promise) {
3641
+ promise = executeRpc(payloadColumns, payloadOptions, callsiteStore.resolve(callsite));
3642
+ }
3643
+ return promise;
3644
+ };
3645
+ const builder = {};
3646
+ const filterMethods = createRpcFilterMethods(state.filters, builder);
3647
+ Object.assign(builder, filterMethods, {
3648
+ select(columns = selectedColumns, options) {
3649
+ selectedColumns = columns;
3650
+ selectedOptions = options ?? selectedOptions;
3651
+ return run(columns, options, captureTraceCallsite(tracer));
3652
+ },
3653
+ async single(columns, options) {
3654
+ const result = await run(columns, options, captureTraceCallsite(tracer));
3655
+ return toSingleResult(result);
3656
+ },
3657
+ maybeSingle(columns, options) {
3658
+ return builder.single(columns, options);
3659
+ },
3660
+ order(column, options) {
3661
+ state.order = { column, ascending: options?.ascending ?? true };
3662
+ return builder;
3663
+ },
3664
+ limit(count) {
3665
+ state.limit = count;
3666
+ return builder;
3667
+ },
3668
+ offset(count) {
3669
+ state.offset = count;
3670
+ return builder;
3671
+ },
3672
+ range(from, to) {
3673
+ state.offset = from;
3674
+ state.limit = to - from + 1;
3675
+ return builder;
3676
+ },
3677
+ then(onfulfilled, onrejected) {
3678
+ return run(selectedColumns, selectedOptions).then(onfulfilled, onrejected);
3679
+ },
3680
+ catch(onrejected) {
3681
+ return run(selectedColumns, selectedOptions).catch(onrejected);
3682
+ },
3683
+ finally(onfinally) {
3684
+ return run(selectedColumns, selectedOptions).finally(onfinally);
3685
+ }
3686
+ });
3687
+ return builder;
3688
+ }
3689
+ function createTableBuilder(tableName, client, formatGatewayResult, tracer, experimental) {
3690
+ const state = {
3691
+ conditions: []
3692
+ };
3693
+ const addCondition = (operator, column, value, hints) => {
3694
+ const condition = { operator };
3695
+ if (column) {
3696
+ condition.column = column;
3697
+ if (operator === "eq") {
3698
+ condition.eq_column = column;
3699
+ }
3700
+ }
3701
+ if (value !== void 0) {
3702
+ condition.value = value;
3703
+ if (operator === "eq") {
3704
+ condition.eq_value = value;
3705
+ }
3706
+ }
3707
+ if (hints?.valueCast) {
3708
+ condition.value_cast = hints.valueCast;
3709
+ if (operator === "eq") {
3710
+ condition.eq_value_cast = hints.valueCast;
3711
+ }
3712
+ }
3713
+ if (hints?.columnCast) {
3714
+ condition.column_cast = hints.columnCast;
3715
+ if (operator === "eq") {
3716
+ condition.eq_column_cast = hints.columnCast;
3717
+ }
3718
+ }
3719
+ state.conditions.push(condition);
3720
+ };
3721
+ const snapshotState = () => ({
3722
+ conditions: state.conditions.map((condition) => ({ ...condition })),
3723
+ limit: state.limit,
3724
+ offset: state.offset,
3725
+ order: state.order ? { ...state.order } : void 0,
3726
+ currentPage: state.currentPage,
3727
+ pageSize: state.pageSize,
3728
+ totalPages: state.totalPages
3729
+ });
3730
+ const builder = {};
3731
+ const filterMethods = createFilterMethods(
3732
+ state,
3733
+ addCondition,
3734
+ builder
3735
+ );
3736
+ const runSelect = async (columns = DEFAULT_COLUMNS, options, executionState = snapshotState(), callsite) => {
3737
+ const resolvedTableName = resolveTableNameForCall(tableName, options?.schema);
3738
+ const conditions = executionState.conditions.length ? executionState.conditions.map((condition) => ({ ...condition })) : void 0;
3739
+ const hasTypedEqualityComparison = conditions?.some(
3740
+ (condition) => condition.operator === "eq" && (condition.value_cast !== void 0 || condition.column_cast !== void 0)
3741
+ ) ?? false;
3742
+ if (hasTypedEqualityComparison && !options?.head && !options?.count && conditions) {
3743
+ const query = buildTypedSelectQuery({
3744
+ tableName: resolvedTableName,
3745
+ columns,
3746
+ conditions,
3747
+ limit: executionState.limit,
3748
+ offset: executionState.offset,
3749
+ currentPage: executionState.currentPage,
3750
+ pageSize: executionState.pageSize,
3751
+ order: executionState.order
3752
+ });
3753
+ if (query) {
3754
+ const payload2 = { query };
3755
+ return executeWithQueryTrace(
3756
+ tracer,
3757
+ {
3758
+ operation: "select",
3759
+ endpoint: "/gateway/query",
3760
+ table: resolvedTableName,
3761
+ sql: query,
3762
+ payload: payload2,
3763
+ options
3764
+ },
3765
+ async () => {
3766
+ const queryResponse = await client.queryGateway(payload2, options);
3767
+ return formatGatewayResult(queryResponse, { table: resolvedTableName, operation: "select" });
3768
+ },
3769
+ callsite
3770
+ );
3771
+ }
3772
+ }
3773
+ const payload = {
3774
+ table_name: resolvedTableName,
3775
+ columns,
3776
+ conditions,
3777
+ limit: executionState.limit,
3778
+ offset: executionState.offset,
3779
+ current_page: executionState.currentPage,
3780
+ page_size: executionState.pageSize,
3781
+ total_pages: executionState.totalPages,
3782
+ sort_by: executionState.order,
3783
+ strip_nulls: options?.stripNulls ?? true,
3784
+ count: options?.count,
3785
+ head: options?.head
3786
+ };
3787
+ const sql = buildDebugSelectQuery({
3788
+ tableName: resolvedTableName,
3789
+ columns,
3790
+ conditions,
3791
+ limit: executionState.limit,
3792
+ offset: executionState.offset,
3793
+ currentPage: executionState.currentPage,
3794
+ pageSize: executionState.pageSize,
3795
+ order: executionState.order
3796
+ });
3797
+ return executeWithQueryTrace(
3798
+ tracer,
3799
+ {
3800
+ operation: "select",
3801
+ endpoint: "/gateway/fetch",
3802
+ table: resolvedTableName,
3803
+ sql,
3804
+ payload,
3805
+ options
3806
+ },
3807
+ async () => {
3808
+ const response = await client.fetchGateway(payload, options);
3809
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
3810
+ },
3811
+ callsite
3812
+ );
3813
+ };
3814
+ const createSelectChain = (columns, options, initialCallsite) => {
3815
+ const chain = {};
3816
+ const callsiteStore = createTraceCallsiteStore(tracer, initialCallsite);
3817
+ const filterMethods2 = createFilterMethods(state, addCondition, chain);
3818
+ Object.assign(chain, filterMethods2, {
3819
+ async single(cols, opts) {
3820
+ const r = await runSelect(
3821
+ cols ?? columns,
3822
+ opts ?? options,
3823
+ snapshotState(),
3824
+ callsiteStore.resolve(captureTraceCallsite(tracer))
3825
+ );
3826
+ return toSingleResult(r);
3827
+ },
3828
+ maybeSingle(cols, opts) {
3829
+ return chain.single(cols, opts);
3830
+ },
3831
+ then(onfulfilled, onrejected) {
3832
+ return runSelect(
3833
+ columns,
3834
+ options,
3835
+ snapshotState(),
3836
+ callsiteStore.resolve()
3837
+ ).then(onfulfilled, onrejected);
3838
+ },
3839
+ catch(onrejected) {
3840
+ return runSelect(columns, options, snapshotState(), callsiteStore.resolve()).catch(
3841
+ onrejected
3842
+ );
3843
+ },
3844
+ finally(onfinally) {
3845
+ return runSelect(columns, options, snapshotState(), callsiteStore.resolve()).finally(
3846
+ onfinally
3847
+ );
3848
+ }
3849
+ });
3850
+ return chain;
3851
+ };
3852
+ Object.assign(builder, filterMethods, {
3853
+ reset() {
3854
+ state.conditions = [];
3855
+ state.limit = void 0;
3856
+ state.offset = void 0;
3857
+ state.order = void 0;
3858
+ state.currentPage = void 0;
3859
+ state.pageSize = void 0;
3860
+ state.totalPages = void 0;
3861
+ return builder;
3862
+ },
3863
+ select(columns = DEFAULT_COLUMNS, options) {
3864
+ return createSelectChain(columns, options, captureTraceCallsite(tracer));
3865
+ },
3866
+ async findMany(options) {
3867
+ const columns = compileSelectShape(options.select);
3868
+ const baseState = snapshotState();
3869
+ const executionState = snapshotState();
3870
+ const callsite = captureTraceCallsite(tracer);
3871
+ const compiledWhere = compileWhere(options.where);
3872
+ if (compiledWhere?.length) {
3873
+ executionState.conditions.push(...compiledWhere);
3874
+ }
3875
+ if (options.orderBy !== void 0) {
3876
+ executionState.order = compileOrderBy(options.orderBy);
3877
+ }
3878
+ if (options.limit !== void 0) {
3879
+ executionState.limit = options.limit;
3880
+ }
3881
+ if (experimental?.findManyAst && canUseFindManyAstTransport(baseState)) {
3882
+ const resolvedTableName = resolveTableNameForCall(tableName, void 0);
3883
+ const payload = {
3884
+ table_name: resolvedTableName,
3885
+ select: options.select
3886
+ };
3887
+ if (options.where !== void 0) {
3888
+ payload.where = options.where;
3889
+ }
3890
+ const astOrder = toFindManyAstOrder(executionState.order);
3891
+ if (astOrder !== void 0) {
3892
+ payload.orderBy = astOrder;
3893
+ }
3894
+ if (executionState.limit !== void 0) {
3895
+ payload.limit = executionState.limit;
3896
+ }
3897
+ const sql = buildDebugSelectQuery({
3898
+ tableName: resolvedTableName,
3899
+ columns,
3900
+ conditions: executionState.conditions,
3901
+ limit: executionState.limit,
3902
+ order: executionState.order
3903
+ });
3904
+ return executeWithQueryTrace(
3905
+ tracer,
3906
+ {
3907
+ operation: "select",
3908
+ endpoint: "/gateway/fetch",
3909
+ table: resolvedTableName,
3910
+ sql,
3911
+ payload
3912
+ },
3913
+ async () => {
3914
+ const response = await client.fetchGateway(
3915
+ payload
3916
+ );
3917
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
3918
+ },
3919
+ callsite
3920
+ );
3921
+ }
3922
+ return runSelect(
3923
+ columns,
3924
+ void 0,
3925
+ executionState,
3926
+ callsite
3927
+ );
3928
+ },
3929
+ insert(values, options) {
3930
+ const mutationCallsite = captureTraceCallsite(tracer);
3931
+ if (Array.isArray(values)) {
3932
+ const executeInsertMany = async (columns, selectOptions, callsite) => {
3933
+ const mergedOptions = mergeOptions(options, selectOptions);
3934
+ const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
3935
+ const payload = {
3936
+ table_name: resolvedTableName,
3937
+ insert_body: asAthenaJsonObjectArray(values)
3938
+ };
3939
+ if (columns) payload.columns = columns;
3940
+ if (mergedOptions?.count) payload.count = mergedOptions.count;
3941
+ if (mergedOptions?.head) payload.head = mergedOptions.head;
3942
+ if (mergedOptions?.defaultToNull !== void 0) {
3943
+ payload.default_to_null = mergedOptions.defaultToNull;
3944
+ }
3945
+ const sql = buildInsertDebugSql(payload);
3946
+ return executeWithQueryTrace(
3947
+ tracer,
3948
+ {
3949
+ operation: "insert",
3950
+ endpoint: "/gateway/insert",
3951
+ table: resolvedTableName,
3952
+ sql,
3953
+ payload,
3954
+ options: mergedOptions
3955
+ },
3956
+ async () => {
3957
+ const response = await client.insertGateway(payload, mergedOptions);
3958
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
3959
+ },
3960
+ callsite
3961
+ );
3962
+ };
3963
+ return createMutationQuery(executeInsertMany, DEFAULT_COLUMNS, tracer, mutationCallsite);
3964
+ }
3965
+ const executeInsertOne = async (columns, selectOptions, callsite) => {
3966
+ const mergedOptions = mergeOptions(options, selectOptions);
3967
+ const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
3968
+ const payload = {
3969
+ table_name: resolvedTableName,
3970
+ insert_body: asAthenaJsonObject(values)
3971
+ };
3972
+ if (columns) payload.columns = columns;
3973
+ if (mergedOptions?.count) payload.count = mergedOptions.count;
3974
+ if (mergedOptions?.head) payload.head = mergedOptions.head;
3975
+ if (mergedOptions?.defaultToNull !== void 0) {
3976
+ payload.default_to_null = mergedOptions.defaultToNull;
3977
+ }
3978
+ const sql = buildInsertDebugSql(payload);
3979
+ return executeWithQueryTrace(
3980
+ tracer,
3981
+ {
3982
+ operation: "insert",
3983
+ endpoint: "/gateway/insert",
3984
+ table: resolvedTableName,
3985
+ sql,
3986
+ payload,
3987
+ options: mergedOptions
3988
+ },
3989
+ async () => {
3990
+ const response = await client.insertGateway(payload, mergedOptions);
3991
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
3992
+ },
3993
+ callsite
3994
+ );
3995
+ };
3996
+ return createMutationQuery(executeInsertOne, DEFAULT_COLUMNS, tracer, mutationCallsite);
3997
+ },
3998
+ upsert(values, options) {
3999
+ const mutationCallsite = captureTraceCallsite(tracer);
4000
+ if (Array.isArray(values)) {
4001
+ const executeUpsertMany = async (columns, selectOptions, callsite) => {
4002
+ const mergedOptions = mergeOptions(options, selectOptions);
4003
+ const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
4004
+ const payload = {
4005
+ table_name: resolvedTableName,
4006
+ insert_body: asAthenaJsonObjectArray(values),
4007
+ update_body: options?.updateBody ? asAthenaJsonObject(options.updateBody) : void 0
4008
+ };
4009
+ if (columns) payload.columns = columns;
4010
+ if (options?.onConflict) payload.on_conflict = options.onConflict;
4011
+ if (mergedOptions?.count) payload.count = mergedOptions.count;
4012
+ if (mergedOptions?.head) payload.head = mergedOptions.head;
4013
+ if (mergedOptions?.defaultToNull !== void 0) {
4014
+ payload.default_to_null = mergedOptions.defaultToNull;
4015
+ }
4016
+ const sql = buildInsertDebugSql(payload);
4017
+ return executeWithQueryTrace(
4018
+ tracer,
4019
+ {
4020
+ operation: "upsert",
4021
+ endpoint: "/gateway/insert",
4022
+ table: resolvedTableName,
4023
+ sql,
4024
+ payload,
4025
+ options: mergedOptions
4026
+ },
4027
+ async () => {
4028
+ const response = await client.insertGateway(payload, mergedOptions);
4029
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
4030
+ },
4031
+ callsite
4032
+ );
4033
+ };
4034
+ return createMutationQuery(executeUpsertMany, DEFAULT_COLUMNS, tracer, mutationCallsite);
4035
+ }
4036
+ const executeUpsertOne = async (columns, selectOptions, callsite) => {
4037
+ const mergedOptions = mergeOptions(options, selectOptions);
4038
+ const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
4039
+ const payload = {
4040
+ table_name: resolvedTableName,
4041
+ insert_body: asAthenaJsonObject(values),
4042
+ update_body: options?.updateBody ? asAthenaJsonObject(options.updateBody) : void 0
4043
+ };
4044
+ if (columns) payload.columns = columns;
4045
+ if (options?.onConflict) payload.on_conflict = options.onConflict;
4046
+ if (mergedOptions?.count) payload.count = mergedOptions.count;
4047
+ if (mergedOptions?.head) payload.head = mergedOptions.head;
4048
+ if (mergedOptions?.defaultToNull !== void 0) {
4049
+ payload.default_to_null = mergedOptions.defaultToNull;
4050
+ }
4051
+ const sql = buildInsertDebugSql(payload);
4052
+ return executeWithQueryTrace(
4053
+ tracer,
4054
+ {
4055
+ operation: "upsert",
4056
+ endpoint: "/gateway/insert",
4057
+ table: resolvedTableName,
4058
+ sql,
4059
+ payload,
4060
+ options: mergedOptions
4061
+ },
4062
+ async () => {
4063
+ const response = await client.insertGateway(payload, mergedOptions);
4064
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
4065
+ },
4066
+ callsite
4067
+ );
4068
+ };
4069
+ return createMutationQuery(executeUpsertOne, DEFAULT_COLUMNS, tracer, mutationCallsite);
4070
+ },
4071
+ update(values, options) {
4072
+ const mutationCallsite = captureTraceCallsite(tracer);
4073
+ const executeUpdate = async (columns, selectOptions, callsite) => {
4074
+ const filters = state.conditions.length ? [...state.conditions] : void 0;
4075
+ const mergedOptions = mergeOptions(options, selectOptions);
4076
+ const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
4077
+ const payload = {
4078
+ table_name: resolvedTableName,
4079
+ set: asAthenaJsonObject(values),
4080
+ conditions: filters,
4081
+ strip_nulls: mergedOptions?.stripNulls ?? true
4082
+ };
4083
+ if (state.order) payload.sort_by = state.order;
4084
+ if (state.currentPage !== void 0) payload.current_page = state.currentPage;
4085
+ if (state.pageSize !== void 0) payload.page_size = state.pageSize;
4086
+ if (state.totalPages !== void 0) payload.total_pages = state.totalPages;
4087
+ if (columns) payload.columns = columns;
4088
+ const sql = buildUpdateDebugSql(payload);
4089
+ return executeWithQueryTrace(
4090
+ tracer,
4091
+ {
4092
+ operation: "update",
4093
+ endpoint: "/gateway/update",
4094
+ table: resolvedTableName,
4095
+ sql,
4096
+ payload,
4097
+ options: mergedOptions
4098
+ },
4099
+ async () => {
4100
+ const response = await client.updateGateway(payload, mergedOptions);
4101
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "update" });
4102
+ },
4103
+ callsite
4104
+ );
4105
+ };
4106
+ const mutation = createMutationQuery(executeUpdate, null, tracer, mutationCallsite);
4107
+ const updateChain = {};
4108
+ const filterMethods2 = createFilterMethods(state, addCondition, updateChain);
4109
+ Object.assign(updateChain, filterMethods2, mutation);
4110
+ return updateChain;
4111
+ },
4112
+ delete(options) {
4113
+ const filters = state.conditions.length ? [...state.conditions] : void 0;
4114
+ const resourceId = options?.resourceId ?? getResourceId(state);
4115
+ if (!resourceId && !filters?.length) {
4116
+ throw new Error('delete requires a resource_id either via eq("resource_id", ...) or options.resourceId');
4117
+ }
4118
+ const mutationCallsite = captureTraceCallsite(tracer);
4119
+ const executeDelete = async (columns, selectOptions, callsite) => {
4120
+ const mergedOptions = mergeOptions(options, selectOptions);
4121
+ const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
4122
+ const payload = {
4123
+ table_name: resolvedTableName,
4124
+ resource_id: resourceId,
4125
+ conditions: filters
4126
+ };
4127
+ if (state.order) payload.sort_by = state.order;
4128
+ if (state.currentPage !== void 0) payload.current_page = state.currentPage;
4129
+ if (state.pageSize !== void 0) payload.page_size = state.pageSize;
4130
+ if (state.totalPages !== void 0) payload.total_pages = state.totalPages;
4131
+ if (columns) payload.columns = columns;
4132
+ const sql = buildDeleteDebugSql(payload);
4133
+ return executeWithQueryTrace(
4134
+ tracer,
4135
+ {
4136
+ operation: "delete",
4137
+ endpoint: "/gateway/delete",
4138
+ table: resolvedTableName,
4139
+ sql,
4140
+ payload,
4141
+ options: mergedOptions
4142
+ },
4143
+ async () => {
4144
+ const response = await client.deleteGateway(payload, mergedOptions);
4145
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "delete" });
4146
+ },
4147
+ callsite
4148
+ );
4149
+ };
4150
+ return createMutationQuery(executeDelete, null, tracer, mutationCallsite);
4151
+ },
4152
+ async single(columns, options) {
4153
+ const response = await runSelect(
4154
+ columns ?? DEFAULT_COLUMNS,
4155
+ options,
4156
+ snapshotState(),
4157
+ captureTraceCallsite(tracer)
4158
+ );
4159
+ return toSingleResult(response);
4160
+ },
4161
+ async maybeSingle(columns, options) {
4162
+ return builder.single(columns, options);
4163
+ }
4164
+ });
4165
+ return builder;
4166
+ }
4167
+ function createQueryBuilder(client, formatGatewayResult, tracer) {
4168
+ return async function query(query, options) {
4169
+ const normalizedQuery = query.trim();
4170
+ if (!normalizedQuery) {
4171
+ throw new Error("query requires a non-empty string");
4172
+ }
4173
+ const payload = { query: normalizedQuery };
4174
+ const callsite = captureTraceCallsite(tracer);
4175
+ return executeWithQueryTrace(
4176
+ tracer,
4177
+ {
4178
+ operation: "query",
4179
+ endpoint: "/gateway/query",
4180
+ sql: normalizedQuery,
4181
+ payload,
4182
+ options
4183
+ },
4184
+ async () => {
4185
+ const response = await client.queryGateway(payload, options);
4186
+ return formatGatewayResult(response, { operation: "query" });
4187
+ },
4188
+ callsite
4189
+ );
4190
+ };
4191
+ }
4192
+ function createClientFromConfig(config) {
4193
+ const gateway = createAthenaGatewayClient({
4194
+ baseUrl: config.baseUrl,
4195
+ apiKey: config.apiKey,
4196
+ client: config.client,
4197
+ backend: config.backend,
4198
+ headers: config.headers
4199
+ });
4200
+ const formatGatewayResult = createResultFormatter(config.experimental);
4201
+ const queryTracer = createQueryTracer(config.experimental);
4202
+ const auth = createAuthClient(config.auth);
4203
+ const from = (table) => createTableBuilder(table, gateway, formatGatewayResult, queryTracer, config.experimental);
4204
+ const rpc = (fn, args, options) => {
4205
+ const normalizedFn = fn.trim();
4206
+ if (!normalizedFn) {
4207
+ throw new Error("rpc requires a function name");
4208
+ }
4209
+ return createRpcBuilder(
4210
+ normalizedFn,
4211
+ args,
4212
+ options,
4213
+ gateway,
4214
+ formatGatewayResult,
4215
+ queryTracer,
4216
+ captureTraceCallsite(queryTracer)
4217
+ );
4218
+ };
4219
+ const query = createQueryBuilder(gateway, formatGatewayResult, queryTracer);
4220
+ const db = createDbModule({ from, rpc, query });
4221
+ return {
4222
+ from,
4223
+ db,
4224
+ rpc,
4225
+ query,
4226
+ auth: auth.auth
4227
+ };
4228
+ }
4229
+ var DEFAULT_BACKEND = { type: "athena" };
4230
+ function toBackendConfig(b) {
4231
+ if (!b) return DEFAULT_BACKEND;
4232
+ return typeof b === "string" ? { type: b } : b;
4233
+ }
4234
+ function mergeAuthClientConfig(current, next) {
4235
+ const merged = {
4236
+ ...current ?? {},
4237
+ ...next
4238
+ };
4239
+ if (current?.headers || next.headers) {
4240
+ merged.headers = {
4241
+ ...current?.headers ?? {},
4242
+ ...next.headers ?? {}
4243
+ };
4244
+ }
4245
+ return merged;
4246
+ }
4247
+ function mergeExperimentalOptions(current, next) {
4248
+ const merged = {
4249
+ ...current ?? {},
4250
+ ...next
4251
+ };
4252
+ if (current?.traceQueries && typeof current.traceQueries === "object" && next.traceQueries && typeof next.traceQueries === "object") {
4253
+ merged.traceQueries = {
4254
+ ...current.traceQueries,
4255
+ ...next.traceQueries
4256
+ };
4257
+ }
4258
+ return merged;
4259
+ }
4260
+ var AthenaClientBuilderImpl = class {
4261
+ baseUrl;
4262
+ apiKey;
4263
+ backendConfig = DEFAULT_BACKEND;
4264
+ clientName;
4265
+ defaultHeaders;
4266
+ authConfig;
4267
+ experimentalOptions;
4268
+ isHealthTrackingEnabled = false;
4269
+ url(url) {
4270
+ this.baseUrl = url;
4271
+ return this;
4272
+ }
4273
+ key(apiKey) {
4274
+ this.apiKey = apiKey;
4275
+ return this;
4276
+ }
4277
+ backend(backend) {
4278
+ this.backendConfig = toBackendConfig(backend);
4279
+ return this;
4280
+ }
4281
+ client(clientName) {
4282
+ this.clientName = clientName;
4283
+ return this;
4284
+ }
4285
+ headers(headers) {
4286
+ this.defaultHeaders = headers;
4287
+ return this;
4288
+ }
4289
+ auth(config) {
4290
+ this.authConfig = mergeAuthClientConfig(this.authConfig, config);
4291
+ return this;
4292
+ }
4293
+ experimental(options) {
4294
+ this.experimentalOptions = mergeExperimentalOptions(this.experimentalOptions, options);
4295
+ return this;
4296
+ }
4297
+ options(options) {
4298
+ if (options.client !== void 0) {
4299
+ this.clientName = options.client;
4300
+ }
4301
+ if (options.backend !== void 0) {
4302
+ this.backendConfig = toBackendConfig(options.backend);
4303
+ }
4304
+ if (options.headers !== void 0) {
4305
+ this.defaultHeaders = {
4306
+ ...this.defaultHeaders ?? {},
4307
+ ...options.headers
4308
+ };
4309
+ }
4310
+ if (options.auth !== void 0) {
4311
+ this.authConfig = mergeAuthClientConfig(this.authConfig, options.auth);
4312
+ }
4313
+ if (options.experimental !== void 0) {
4314
+ this.experimentalOptions = mergeExperimentalOptions(this.experimentalOptions, options.experimental);
4315
+ }
4316
+ return this;
4317
+ }
4318
+ healthTracking(enabled) {
4319
+ this.isHealthTrackingEnabled = enabled;
4320
+ return this;
4321
+ }
4322
+ build() {
4323
+ if (!this.baseUrl || !this.apiKey) {
4324
+ throw new Error("AthenaClient requires url and key; call .url() and .key() before .build()");
4325
+ }
4326
+ return createClientFromConfig({
4327
+ baseUrl: this.baseUrl,
4328
+ apiKey: this.apiKey,
4329
+ client: this.clientName,
4330
+ backend: this.backendConfig,
4331
+ headers: this.defaultHeaders,
4332
+ healthTracking: this.isHealthTrackingEnabled,
4333
+ auth: this.authConfig,
4334
+ experimental: this.experimentalOptions
4335
+ });
4336
+ }
4337
+ };
4338
+ var AthenaClient = class _AthenaClient {
4339
+ /** Create a fluent builder for a strongly-typed Athena SDK client. */
4340
+ static builder() {
4341
+ return new AthenaClientBuilderImpl();
4342
+ }
4343
+ /** Build a client from process environment variables. */
4344
+ static fromEnvironment() {
4345
+ const url = process.env.ATHENA_URL ?? process.env.ATHENA_GATEWAY_URL;
4346
+ const key = process.env.ATHENA_API_KEY ?? process.env.ATHENA_GATEWAY_API_KEY;
4347
+ if (!url || !key) {
4348
+ throw new Error(
4349
+ "ATHENA_URL and ATHENA_API_KEY (or ATHENA_GATEWAY_URL and ATHENA_GATEWAY_API_KEY) are required"
4350
+ );
4351
+ }
4352
+ return _AthenaClient.builder().url(url).key(key).build();
4353
+ }
4354
+ };
4355
+ function createClient(url, apiKey, options) {
4356
+ return createClientFromConfig({
4357
+ baseUrl: url,
4358
+ apiKey,
4359
+ client: options?.client,
4360
+ backend: toBackendConfig(options?.backend),
4361
+ headers: options?.headers,
4362
+ auth: options?.auth,
4363
+ experimental: options?.experimental
4364
+ });
4365
+ }
4366
+
4367
+ // src/gateway/types.ts
4368
+ var Backend = {
4369
+ Athena: { type: "athena" },
4370
+ Postgrest: { type: "postgrest" },
4371
+ PostgreSQL: { type: "postgresql" },
4372
+ ScyllaDB: { type: "scylladb" }
4373
+ };
4374
+
4375
+ // src/schema/definitions.ts
4376
+ function defineModel(input) {
4377
+ return input;
4378
+ }
4379
+ function defineSchema(models) {
4380
+ return { models };
4381
+ }
4382
+ function defineDatabase(schemas) {
4383
+ return { schemas };
4384
+ }
4385
+ function defineRegistry(databases) {
4386
+ return databases;
4387
+ }
4388
+
4389
+ // src/schema/typed-client.ts
4390
+ var TenantHeaderMapper = class {
4391
+ constructor(tenantKeyMap) {
4392
+ this.tenantKeyMap = tenantKeyMap;
4393
+ }
4394
+ apply(baseHeaders, tenantContext) {
4395
+ const headers = {
4396
+ ...baseHeaders ?? {}
4397
+ };
4398
+ for (const [tenantKey, headerName] of Object.entries(this.tenantKeyMap)) {
4399
+ const tenantValue = tenantContext[tenantKey];
4400
+ if (tenantValue === void 0 || tenantValue === null) {
4401
+ continue;
4402
+ }
4403
+ headers[headerName] = String(tenantValue);
4404
+ }
4405
+ return Object.keys(headers).length > 0 ? headers : void 0;
4406
+ }
4407
+ };
4408
+ var RegistryNavigator = class {
4409
+ constructor(registry) {
4410
+ this.registry = registry;
4411
+ }
4412
+ resolveModel(database, schema, model) {
4413
+ const databaseDef = this.registry[database];
4414
+ if (!databaseDef) {
4415
+ throw new Error(`Unknown database "${database}"`);
4416
+ }
4417
+ const schemaDef = databaseDef.schemas[schema];
4418
+ if (!schemaDef) {
4419
+ throw new Error(`Unknown schema "${schema}" in database "${database}"`);
4420
+ }
4421
+ const modelDef = schemaDef.models[model];
4422
+ if (!modelDef) {
4423
+ throw new Error(`Unknown model "${model}" in schema "${schema}"`);
4424
+ }
4425
+ return modelDef;
4426
+ }
4427
+ resolveTableName(schema, model, modelDef) {
4428
+ if (modelDef.meta.tableName) {
4429
+ return modelDef.meta.tableName;
4430
+ }
4431
+ const schemaName = modelDef.meta.schema ?? schema;
4432
+ const modelName = modelDef.meta.model ?? model;
4433
+ return `${schemaName}.${modelName}`;
4434
+ }
4435
+ };
4436
+ var TypedAthenaClientImpl = class _TypedAthenaClientImpl {
4437
+ registry;
4438
+ tenantKeyMap;
4439
+ tenantContext;
4440
+ db;
4441
+ baseClient;
4442
+ registryNavigator;
4443
+ tenantHeaderMapper;
4444
+ clientOptions;
4445
+ url;
4446
+ apiKey;
4447
+ constructor(input) {
4448
+ this.registry = input.registry;
4449
+ this.url = input.url;
4450
+ this.apiKey = input.apiKey;
4451
+ const tenantKeyMap = input.options?.tenantKeyMap ?? {};
4452
+ const tenantContext = input.options?.tenantContext ?? {};
4453
+ this.tenantKeyMap = tenantKeyMap;
4454
+ this.tenantContext = tenantContext;
4455
+ this.tenantHeaderMapper = new TenantHeaderMapper(tenantKeyMap);
4456
+ this.registryNavigator = new RegistryNavigator(input.registry);
4457
+ this.clientOptions = {
4458
+ backend: input.options?.backend,
4459
+ client: input.options?.client,
4460
+ headers: input.options?.headers
4461
+ };
4462
+ this.baseClient = createClient(this.url, this.apiKey, {
4463
+ backend: this.clientOptions.backend,
4464
+ client: this.clientOptions.client,
4465
+ headers: this.tenantHeaderMapper.apply(this.clientOptions.headers, tenantContext)
4466
+ });
4467
+ this.db = this.baseClient.db;
4468
+ }
4469
+ from(table) {
4470
+ return this.baseClient.from(table);
4471
+ }
4472
+ rpc(fn, args, options) {
4473
+ return this.baseClient.rpc(fn, args, options);
4474
+ }
4475
+ query(query, options) {
4476
+ return this.baseClient.query(query, options);
4477
+ }
4478
+ withTenantContext(context) {
4479
+ return new _TypedAthenaClientImpl({
4480
+ registry: this.registry,
4481
+ url: this.url,
4482
+ apiKey: this.apiKey,
4483
+ options: {
4484
+ ...this.clientOptions,
4485
+ tenantKeyMap: this.tenantKeyMap,
4486
+ tenantContext: {
4487
+ ...this.tenantContext,
4488
+ ...context ?? {}
4489
+ }
4490
+ }
4491
+ });
4492
+ }
4493
+ fromModel(database, schema, model) {
4494
+ const modelDef = this.registryNavigator.resolveModel(database, schema, model);
4495
+ const tableName = this.registryNavigator.resolveTableName(schema, model, modelDef);
4496
+ return this.baseClient.from(tableName);
4497
+ }
4498
+ };
4499
+ function createTypedClient(registry, url, apiKey, options) {
4500
+ return new TypedAthenaClientImpl({
4501
+ registry,
4502
+ url,
4503
+ apiKey,
4504
+ options
4505
+ });
4506
+ }
4507
+
4508
+ // src/schema/model-form.ts
4509
+ function resolveNullishValue(mode) {
4510
+ if (mode === "undefined") return void 0;
4511
+ if (mode === "null") return null;
4512
+ return "";
4513
+ }
4514
+ function isRecord7(value) {
4515
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
4516
+ }
4517
+ function isNullableColumn(model, key) {
4518
+ const nullable = model.meta.nullable;
4519
+ return nullable?.[key] === true;
4520
+ }
4521
+ function toModelFormDefaults(model, values, options) {
4522
+ const source = values;
4523
+ if (!isRecord7(source)) {
4524
+ return {};
4525
+ }
4526
+ const mode = options?.nullishMode ?? "empty-string";
4527
+ const nullishValue = resolveNullishValue(mode);
4528
+ const result = {};
4529
+ for (const [key, value] of Object.entries(source)) {
4530
+ if (value === null && isNullableColumn(model, key)) {
4531
+ result[key] = nullishValue;
4532
+ continue;
4533
+ }
4534
+ result[key] = value;
4535
+ }
4536
+ return result;
4537
+ }
4538
+ function toModelPayload(model, formValues, options) {
4539
+ const emptyStringAsNull = options?.emptyStringAsNull ?? true;
4540
+ const stripUndefined = options?.stripUndefined ?? true;
4541
+ const result = {};
4542
+ for (const [key, rawValue] of Object.entries(formValues)) {
4543
+ if (rawValue === void 0 && stripUndefined) {
4544
+ continue;
4545
+ }
4546
+ if (emptyStringAsNull && rawValue === "" && isNullableColumn(model, key)) {
4547
+ result[key] = null;
4548
+ continue;
4549
+ }
4550
+ result[key] = rawValue;
4551
+ }
4552
+ return result;
4553
+ }
4554
+ function createModelFormAdapter(model) {
4555
+ return {
4556
+ model,
4557
+ toDefaults(values, options) {
4558
+ return toModelFormDefaults(model, values, options);
4559
+ },
4560
+ toInsert(values, options) {
4561
+ return toModelPayload(model, values, options);
4562
+ },
4563
+ toUpdate(values, options) {
4564
+ return toModelPayload(model, values, options);
4565
+ }
4566
+ };
4567
+ }
4568
+
4569
+ // src/generator/schema-selection.ts
4570
+ var DEFAULT_POSTGRES_SCHEMAS = ["public"];
4571
+ function collectSchemaNames(input) {
4572
+ if (!input) {
4573
+ return [];
4574
+ }
4575
+ const values = typeof input === "string" ? [input] : input;
4576
+ return values.flatMap((value) => String(value).split(","));
4577
+ }
4578
+ function normalizeSchemaSelection(input) {
4579
+ const schemas = [];
4580
+ const seen = /* @__PURE__ */ new Set();
4581
+ for (const value of collectSchemaNames(input)) {
4582
+ const schema = value.trim();
4583
+ if (!schema || seen.has(schema)) {
4584
+ continue;
4585
+ }
4586
+ seen.add(schema);
4587
+ schemas.push(schema);
4588
+ }
4589
+ return schemas.length > 0 ? schemas : [...DEFAULT_POSTGRES_SCHEMAS];
4590
+ }
4591
+ function resolveProviderSchemas(providerConfig) {
4592
+ if (providerConfig.kind === "postgres") {
4593
+ return normalizeSchemaSelection(providerConfig.schemas);
4594
+ }
4595
+ return [...DEFAULT_POSTGRES_SCHEMAS];
4596
+ }
4597
+
4598
+ // src/generator/postgres-type-mapping.ts
4599
+ var NUMBER_TYPES = /* @__PURE__ */ new Set([
4600
+ "int2",
4601
+ "int4",
4602
+ "float4",
4603
+ "float8",
4604
+ "smallint",
4605
+ "integer",
4606
+ "real",
4607
+ "double precision"
4608
+ ]);
4609
+ var STRING_NUMERIC_TYPES = /* @__PURE__ */ new Set([
4610
+ "int8",
4611
+ "bigint",
4612
+ "serial8",
4613
+ "bigserial",
4614
+ "numeric",
4615
+ "decimal",
4616
+ "money"
4617
+ ]);
4618
+ var TEXT_TYPES = /* @__PURE__ */ new Set([
4619
+ "char",
4620
+ "bpchar",
4621
+ "varchar",
4622
+ "character varying",
4623
+ "text",
4624
+ "citext",
4625
+ "name",
4626
+ "uuid",
4627
+ "date",
4628
+ "time",
4629
+ "timetz",
4630
+ "timestamp",
4631
+ "timestamptz",
4632
+ "interval",
4633
+ "inet",
4634
+ "cidr",
4635
+ "macaddr",
4636
+ "macaddr8",
4637
+ "point",
4638
+ "line",
4639
+ "lseg",
4640
+ "box",
4641
+ "path",
4642
+ "polygon",
4643
+ "circle",
4644
+ "bit",
4645
+ "varbit",
4646
+ "xml",
4647
+ "tsvector",
4648
+ "tsquery",
4649
+ "jsonpath"
4650
+ ]);
4651
+ function normalizeTypeLabel(column) {
4652
+ const preferred = (column.udtName || column.dataType).toLowerCase().trim();
4653
+ if (column.arrayDimensions > 0 && preferred.startsWith("_")) {
4654
+ return preferred.slice(1);
4655
+ }
4656
+ return preferred;
4657
+ }
4658
+ function wrapArrayType(baseType, depth) {
4659
+ let wrapped = baseType;
4660
+ for (let index = 0; index < depth; index += 1) {
4661
+ wrapped = `Array<${wrapped}>`;
4662
+ }
4663
+ return wrapped;
4664
+ }
4665
+ function resolveScalarType(column) {
4666
+ const label = normalizeTypeLabel(column);
4667
+ if (NUMBER_TYPES.has(label)) {
4668
+ return "number";
4669
+ }
4670
+ if (STRING_NUMERIC_TYPES.has(label)) {
4671
+ return "string";
4672
+ }
4673
+ if (label === "bool" || label === "boolean") {
4674
+ return "boolean";
4675
+ }
4676
+ if (label === "bytea") {
4677
+ return "Buffer";
4678
+ }
4679
+ if (label === "json" || label === "jsonb") {
4680
+ return "Record<string, unknown>";
4681
+ }
4682
+ if (TEXT_TYPES.has(label)) {
4683
+ return "string";
4684
+ }
4685
+ if (label.endsWith("range") || label.endsWith("multirange")) {
4686
+ return "string";
4687
+ }
4688
+ return "unknown";
4689
+ }
4690
+ function resolveKindAwareType(column) {
4691
+ if (column.typeKind === "enum") {
4692
+ const values = column.enumValues ?? [];
4693
+ if (values.length === 0) {
4694
+ return "string";
4695
+ }
4696
+ return values.map((value) => `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`).join(" | ");
4697
+ }
4698
+ if (column.typeKind === "composite") {
4699
+ return "Record<string, unknown>";
4700
+ }
4701
+ if (column.typeKind === "domain" || column.typeKind === "range" || column.typeKind === "multirange") {
4702
+ return "string";
4703
+ }
4704
+ return resolveScalarType(column);
4705
+ }
4706
+ function resolvePostgresColumnType(column) {
4707
+ const baseType = resolveKindAwareType(column);
4708
+ if (!column.arrayDimensions || column.arrayDimensions <= 0) {
4709
+ return baseType;
4710
+ }
4711
+ return wrapArrayType(baseType, column.arrayDimensions);
4712
+ }
4713
+
4714
+ // src/browser.ts
4715
+ function throwBrowserUnsupported(apiName) {
4716
+ throw new Error(
4717
+ `@xylex-group/athena: ${apiName} is not available in browser bundles. Use this API in a Node.js runtime.`
4718
+ );
4719
+ }
4720
+ function createPostgresIntrospectionProvider(options) {
4721
+ return throwBrowserUnsupported("createPostgresIntrospectionProvider");
4722
+ }
4723
+ function defineGeneratorConfig(config) {
4724
+ return config;
4725
+ }
4726
+ function findGeneratorConfigPath(cwd) {
4727
+ return throwBrowserUnsupported("findGeneratorConfigPath");
4728
+ }
4729
+ async function loadGeneratorConfig(options = {}) {
4730
+ return throwBrowserUnsupported("loadGeneratorConfig");
4731
+ }
4732
+ function normalizeGeneratorConfig(input) {
4733
+ return throwBrowserUnsupported("normalizeGeneratorConfig");
4734
+ }
4735
+ function generateArtifactsFromSnapshot(snapshot, config) {
4736
+ return throwBrowserUnsupported("generateArtifactsFromSnapshot");
4737
+ }
4738
+ function resolveGeneratorProvider(providerConfig, experimentalFlags) {
4739
+ return throwBrowserUnsupported("resolveGeneratorProvider");
4740
+ }
4741
+ async function runSchemaGenerator(options = {}) {
4742
+ return throwBrowserUnsupported("runSchemaGenerator");
4743
+ }
4744
+
4745
+ exports.AthenaClient = AthenaClient;
4746
+ exports.AthenaError = AthenaError;
4747
+ exports.AthenaErrorCategory = AthenaErrorCategory;
4748
+ exports.AthenaErrorCode = AthenaErrorCode;
4749
+ exports.AthenaErrorKind = AthenaErrorKind;
4750
+ exports.AthenaGatewayError = AthenaGatewayError;
4751
+ exports.Backend = Backend;
4752
+ exports.DEFAULT_POSTGRES_SCHEMAS = DEFAULT_POSTGRES_SCHEMAS;
4753
+ exports.assertInt = assertInt;
4754
+ exports.coerceInt = coerceInt;
4755
+ exports.createAuthClient = createAuthClient;
4756
+ exports.createAuthReactEmailInput = createAuthReactEmailInput;
4757
+ exports.createClient = createClient;
4758
+ exports.createModelFormAdapter = createModelFormAdapter;
4759
+ exports.createPostgresIntrospectionProvider = createPostgresIntrospectionProvider;
4760
+ exports.createTypedClient = createTypedClient;
4761
+ exports.defineAuthEmailTemplate = defineAuthEmailTemplate;
4762
+ exports.defineDatabase = defineDatabase;
4763
+ exports.defineGeneratorConfig = defineGeneratorConfig;
4764
+ exports.defineModel = defineModel;
4765
+ exports.defineRegistry = defineRegistry;
4766
+ exports.defineSchema = defineSchema;
4767
+ exports.findGeneratorConfigPath = findGeneratorConfigPath;
4768
+ exports.generateArtifactsFromSnapshot = generateArtifactsFromSnapshot;
4769
+ exports.identifier = identifier;
4770
+ exports.isAthenaGatewayError = isAthenaGatewayError;
4771
+ exports.isOk = isOk;
4772
+ exports.loadGeneratorConfig = loadGeneratorConfig;
4773
+ exports.normalizeAthenaError = normalizeAthenaError;
4774
+ exports.normalizeGeneratorConfig = normalizeGeneratorConfig;
4775
+ exports.normalizeSchemaSelection = normalizeSchemaSelection;
4776
+ exports.parseBooleanFlag = parseBooleanFlag2;
4777
+ exports.renderAthenaReactEmail = renderAthenaReactEmail;
4778
+ exports.requireAffected = requireAffected;
4779
+ exports.requireSuccess = requireSuccess;
4780
+ exports.resolveGeneratorProvider = resolveGeneratorProvider;
4781
+ exports.resolvePostgresColumnType = resolvePostgresColumnType;
4782
+ exports.resolveProviderSchemas = resolveProviderSchemas;
4783
+ exports.runSchemaGenerator = runSchemaGenerator;
4784
+ exports.toModelFormDefaults = toModelFormDefaults;
4785
+ exports.toModelPayload = toModelPayload;
4786
+ exports.unwrap = unwrap;
4787
+ exports.unwrapOne = unwrapOne;
4788
+ exports.unwrapRows = unwrapRows;
4789
+ exports.withRetry = withRetry;
4790
+ //# sourceMappingURL=browser.cjs.map
4791
+ //# sourceMappingURL=browser.cjs.map