@xylex-group/athena 2.4.0 → 2.6.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 (47) hide show
  1. package/README.md +124 -2
  2. package/bin/athena-js.js +0 -0
  3. package/dist/browser.cjs +2245 -151
  4. package/dist/browser.cjs.map +1 -1
  5. package/dist/browser.d.cts +8 -7
  6. package/dist/browser.d.ts +8 -7
  7. package/dist/browser.js +2238 -152
  8. package/dist/browser.js.map +1 -1
  9. package/dist/cli/index.cjs +1073 -102
  10. package/dist/cli/index.cjs.map +1 -1
  11. package/dist/cli/index.d.cts +3 -3
  12. package/dist/cli/index.d.ts +3 -3
  13. package/dist/cli/index.js +1073 -102
  14. package/dist/cli/index.js.map +1 -1
  15. package/dist/cookies.d.cts +1 -174
  16. package/dist/cookies.d.ts +1 -174
  17. package/dist/index-CVcQCGyG.d.cts +174 -0
  18. package/dist/index-CVcQCGyG.d.ts +174 -0
  19. package/dist/index.cjs +2246 -152
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.cts +8 -7
  22. package/dist/index.d.ts +8 -7
  23. package/dist/index.js +2239 -153
  24. package/dist/index.js.map +1 -1
  25. package/dist/{model-form-GzTqhEzM.d.cts → model-form-BaHWi3gm.d.cts} +9 -5
  26. package/dist/{model-form-C0FAbOaf.d.ts → model-form-Dh6gWjL0.d.ts} +9 -5
  27. package/dist/{pipeline-CR4V15jF.d.ts → pipeline-Ce3pTw5h.d.ts} +1 -1
  28. package/dist/{pipeline-DZeExYMA.d.cts → pipeline-D1ZYeoH7.d.cts} +1 -1
  29. package/dist/{react-email-CQJq92zQ.d.cts → react-email-B8O1Jeff.d.cts} +637 -30
  30. package/dist/{react-email-BuApZuyG.d.ts → react-email-CDEF0jij.d.ts} +637 -30
  31. package/dist/react.cjs +84 -4
  32. package/dist/react.cjs.map +1 -1
  33. package/dist/react.d.cts +4 -4
  34. package/dist/react.d.ts +4 -4
  35. package/dist/react.js +84 -4
  36. package/dist/react.js.map +1 -1
  37. package/dist/{types-D1JvL21V.d.cts → types-CUuo4NDi.d.cts} +1 -1
  38. package/dist/{types-09Q4D86N.d.cts → types-DSX6AT5B.d.cts} +3 -3
  39. package/dist/{types-09Q4D86N.d.ts → types-DSX6AT5B.d.ts} +3 -3
  40. package/dist/{types-DU3gNdFv.d.ts → types-DapchQY5.d.ts} +1 -1
  41. package/dist/utils.cjs +131 -0
  42. package/dist/utils.cjs.map +1 -1
  43. package/dist/utils.d.cts +42 -1
  44. package/dist/utils.d.ts +42 -1
  45. package/dist/utils.js +117 -1
  46. package/dist/utils.js.map +1 -1
  47. package/package.json +193 -192
package/dist/browser.cjs CHANGED
@@ -127,12 +127,685 @@ function buildAthenaGatewayUrl(baseUrl, path) {
127
127
  return `${baseUrl}${path}`;
128
128
  }
129
129
 
130
+ // src/cookies/base64.ts
131
+ function getAtob() {
132
+ const candidate = globalThis.atob;
133
+ return typeof candidate === "function" ? candidate : void 0;
134
+ }
135
+ function getBtoa() {
136
+ const candidate = globalThis.btoa;
137
+ return typeof candidate === "function" ? candidate : void 0;
138
+ }
139
+ function bytesToBinaryString(bytes) {
140
+ let result = "";
141
+ for (const byte of bytes) {
142
+ result += String.fromCharCode(byte);
143
+ }
144
+ return result;
145
+ }
146
+ function binaryStringToBytes(binary) {
147
+ const bytes = new Uint8Array(binary.length);
148
+ for (let i = 0; i < binary.length; i++) {
149
+ bytes[i] = binary.charCodeAt(i);
150
+ }
151
+ return bytes;
152
+ }
153
+ function encodeBase64(bytes) {
154
+ const btoaFn = getBtoa();
155
+ if (btoaFn) {
156
+ return btoaFn(bytesToBinaryString(bytes));
157
+ }
158
+ return Buffer.from(bytes).toString("base64");
159
+ }
160
+ function decodeBase64(base64) {
161
+ const atobFn = getAtob();
162
+ if (atobFn) {
163
+ return binaryStringToBytes(atobFn(base64));
164
+ }
165
+ return new Uint8Array(Buffer.from(base64, "base64"));
166
+ }
167
+ function encodeBytesToBase64Url(bytes) {
168
+ return encodeBase64(bytes).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
169
+ }
170
+ function encodeStringToBase64Url(value) {
171
+ const bytes = new TextEncoder().encode(value);
172
+ return encodeBytesToBase64Url(bytes);
173
+ }
174
+ function decodeBase64UrlToBytes(value) {
175
+ const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
176
+ const paddingLength = normalized.length % 4;
177
+ const padded = paddingLength === 0 ? normalized : `${normalized}${"=".repeat(4 - paddingLength)}`;
178
+ return decodeBase64(padded);
179
+ }
180
+ function decodeBase64UrlToString(value) {
181
+ return new TextDecoder().decode(decodeBase64UrlToBytes(value));
182
+ }
183
+
184
+ // src/cookies/cookie-utils.ts
185
+ var SECURE_COOKIE_PREFIX = "__Secure-";
186
+ function parseCookies(cookieHeader) {
187
+ const cookies = cookieHeader.split("; ");
188
+ const cookieMap = /* @__PURE__ */ new Map();
189
+ cookies.forEach((cookie) => {
190
+ const [name, value] = cookie.split(/=(.*)/s);
191
+ cookieMap.set(name, value);
192
+ });
193
+ return cookieMap;
194
+ }
195
+
196
+ // src/cookies/crypto.ts
197
+ var HS256_ALG = "HS256";
198
+ async function getSubtleCrypto() {
199
+ const globalCrypto = globalThis.crypto;
200
+ if (globalCrypto?.subtle) {
201
+ return globalCrypto.subtle;
202
+ }
203
+ const { webcrypto } = await import('crypto');
204
+ const subtle = webcrypto.subtle;
205
+ if (!subtle) {
206
+ throw new Error("Web Crypto subtle API is unavailable.");
207
+ }
208
+ return subtle;
209
+ }
210
+ async function importHmacKey(secret, usage) {
211
+ const subtle = await getSubtleCrypto();
212
+ return subtle.importKey(
213
+ "raw",
214
+ new TextEncoder().encode(secret),
215
+ {
216
+ name: "HMAC",
217
+ hash: "SHA-256"
218
+ },
219
+ false,
220
+ [usage]
221
+ );
222
+ }
223
+ function bufferToBytes(buffer) {
224
+ return new Uint8Array(buffer);
225
+ }
226
+ function parseJwtPayload(payloadSegment) {
227
+ try {
228
+ const decoded = decodeBase64UrlToString(payloadSegment);
229
+ const payload = JSON.parse(decoded);
230
+ if (!payload || typeof payload !== "object") {
231
+ return null;
232
+ }
233
+ return payload;
234
+ } catch {
235
+ return null;
236
+ }
237
+ }
238
+ function isJwtExpired(payload) {
239
+ const exp = payload.exp;
240
+ if (typeof exp !== "number") {
241
+ return false;
242
+ }
243
+ return exp < Math.floor(Date.now() / 1e3);
244
+ }
245
+ async function signHmacBase64Url(secret, value) {
246
+ const subtle = await getSubtleCrypto();
247
+ const key = await importHmacKey(secret, "sign");
248
+ const signature = await subtle.sign("HMAC", key, new TextEncoder().encode(value));
249
+ return encodeBytesToBase64Url(bufferToBytes(signature));
250
+ }
251
+ async function signJwtHS256(payload, secret, expiresIn = 60 * 5) {
252
+ const now = Math.floor(Date.now() / 1e3);
253
+ const header = { alg: HS256_ALG, typ: "JWT" };
254
+ const fullPayload = {
255
+ ...payload,
256
+ iat: now,
257
+ exp: now + expiresIn
258
+ };
259
+ const headerPart = encodeStringToBase64Url(JSON.stringify(header));
260
+ const payloadPart = encodeStringToBase64Url(JSON.stringify(fullPayload));
261
+ const message = `${headerPart}.${payloadPart}`;
262
+ const signature = await signHmacBase64Url(secret, message);
263
+ return `${message}.${signature}`;
264
+ }
265
+ async function verifyJwtHS256(token, secret) {
266
+ const parts = token.split(".");
267
+ if (parts.length !== 3) {
268
+ return null;
269
+ }
270
+ const [headerPart, payloadPart, signaturePart] = parts;
271
+ if (!headerPart || !payloadPart || !signaturePart) {
272
+ return null;
273
+ }
274
+ let header = null;
275
+ try {
276
+ header = JSON.parse(decodeBase64UrlToString(headerPart));
277
+ } catch {
278
+ return null;
279
+ }
280
+ if (!header || header.alg !== HS256_ALG) {
281
+ return null;
282
+ }
283
+ const payload = parseJwtPayload(payloadPart);
284
+ if (!payload) {
285
+ return null;
286
+ }
287
+ const expectedSignature = await signHmacBase64Url(secret, `${headerPart}.${payloadPart}`);
288
+ if (expectedSignature !== signaturePart) {
289
+ return null;
290
+ }
291
+ if (isJwtExpired(payload)) {
292
+ return null;
293
+ }
294
+ return payload;
295
+ }
296
+
297
+ // src/cookies/session-store.ts
298
+ var ALLOWED_COOKIE_SIZE = 4096;
299
+ var ESTIMATED_EMPTY_COOKIE_SIZE = 200;
300
+ var CHUNK_SIZE = ALLOWED_COOKIE_SIZE - ESTIMATED_EMPTY_COOKIE_SIZE;
301
+ function getChunkIndex(cookieName) {
302
+ const parts = cookieName.split(".");
303
+ const lastPart = parts[parts.length - 1];
304
+ const index = parseInt(lastPart || "0", 10);
305
+ return Number.isNaN(index) ? 0 : index;
306
+ }
307
+ function readExistingChunks(cookieName, ctx) {
308
+ const chunks = {};
309
+ const cookies = parseCookies(ctx.headers?.get("cookie") || "");
310
+ for (const [name, value] of cookies) {
311
+ if (name.startsWith(cookieName)) {
312
+ chunks[name] = value;
313
+ }
314
+ }
315
+ return chunks;
316
+ }
317
+ function joinChunks(chunks) {
318
+ const sortedKeys = Object.keys(chunks).sort((left, right) => getChunkIndex(left) - getChunkIndex(right));
319
+ return sortedKeys.map((key) => chunks[key]).join("");
320
+ }
321
+ function chunkCookie(storeName, cookie, chunks, ctx) {
322
+ const chunkCount = Math.ceil(cookie.value.length / CHUNK_SIZE);
323
+ if (chunkCount === 1) {
324
+ chunks[cookie.name] = cookie.value;
325
+ return [cookie];
326
+ }
327
+ const cookies = [];
328
+ for (let index = 0; index < chunkCount; index++) {
329
+ const name = `${cookie.name}.${index}`;
330
+ const start = index * CHUNK_SIZE;
331
+ const value = cookie.value.substring(start, start + CHUNK_SIZE);
332
+ cookies.push({
333
+ ...cookie,
334
+ name,
335
+ value
336
+ });
337
+ chunks[name] = value;
338
+ }
339
+ ctx.logger?.debug?.(`CHUNKING_${storeName.toUpperCase()}_COOKIE`, {
340
+ message: `${storeName} cookie exceeds allowed ${ALLOWED_COOKIE_SIZE} bytes.`,
341
+ emptyCookieSize: ESTIMATED_EMPTY_COOKIE_SIZE,
342
+ valueSize: cookie.value.length,
343
+ chunkCount,
344
+ chunks: cookies.map((entry) => entry.value.length + ESTIMATED_EMPTY_COOKIE_SIZE)
345
+ });
346
+ return cookies;
347
+ }
348
+ function getCleanCookies(chunks, cookieOptions) {
349
+ const cleanedChunks = {};
350
+ for (const name in chunks) {
351
+ cleanedChunks[name] = {
352
+ name,
353
+ value: "",
354
+ attributes: {
355
+ ...cookieOptions,
356
+ maxAge: 0
357
+ }
358
+ };
359
+ }
360
+ return cleanedChunks;
361
+ }
362
+ var storeFactory = (storeName) => (cookieName, cookieOptions, ctx) => {
363
+ const chunks = readExistingChunks(cookieName, ctx);
364
+ return {
365
+ getValue() {
366
+ return joinChunks(chunks);
367
+ },
368
+ hasChunks() {
369
+ return Object.keys(chunks).length > 0;
370
+ },
371
+ chunk(value, options) {
372
+ const cleanedChunks = getCleanCookies(chunks, cookieOptions);
373
+ for (const name in chunks) {
374
+ delete chunks[name];
375
+ }
376
+ const cookies = cleanedChunks;
377
+ const chunked = chunkCookie(
378
+ storeName,
379
+ {
380
+ name: cookieName,
381
+ value,
382
+ attributes: {
383
+ ...cookieOptions,
384
+ ...options
385
+ }
386
+ },
387
+ chunks,
388
+ ctx
389
+ );
390
+ for (const chunk of chunked) {
391
+ cookies[chunk.name] = chunk;
392
+ }
393
+ return Object.values(cookies);
394
+ },
395
+ clean() {
396
+ const cleanedChunks = getCleanCookies(chunks, cookieOptions);
397
+ for (const name in chunks) {
398
+ delete chunks[name];
399
+ }
400
+ return Object.values(cleanedChunks);
401
+ },
402
+ setCookies(cookies) {
403
+ for (const cookie of cookies) {
404
+ ctx.setCookie(cookie.name, cookie.value, cookie.attributes);
405
+ }
406
+ }
407
+ };
408
+ };
409
+ var createSessionStore = storeFactory("Session");
410
+ var createAccountStore = storeFactory("Account");
411
+
412
+ // src/cookies/index.ts
413
+ var DEFAULT_COOKIE_PREFIX = "athena-auth";
414
+ var LEGACY_COOKIE_PREFIX = "better-auth";
415
+ var DEFAULT_SESSION_MAX_AGE = 7 * 24 * 60 * 60;
416
+ var DEFAULT_CACHE_MAX_AGE = 60 * 5;
417
+ function isProductionRuntime() {
418
+ return typeof process !== "undefined" && process.env?.NODE_ENV === "production";
419
+ }
420
+ function getEnvironmentSecret() {
421
+ if (typeof process === "undefined") {
422
+ return void 0;
423
+ }
424
+ return process.env?.ATHENA_AUTH_SECRET || process.env?.BETTER_AUTH_SECRET || process.env?.AUTH_SECRET;
425
+ }
426
+ function isDynamicBaseURLConfig(baseURL) {
427
+ return typeof baseURL === "object" && baseURL !== null && "allowedHosts" in baseURL && Array.isArray(baseURL.allowedHosts);
428
+ }
429
+ function resolveCookiePrefixes(primaryPrefix) {
430
+ const prefixes = [primaryPrefix];
431
+ if (!prefixes.includes(DEFAULT_COOKIE_PREFIX)) {
432
+ prefixes.push(DEFAULT_COOKIE_PREFIX);
433
+ }
434
+ if (!prefixes.includes(LEGACY_COOKIE_PREFIX)) {
435
+ prefixes.push(LEGACY_COOKIE_PREFIX);
436
+ }
437
+ return prefixes;
438
+ }
439
+ function createError(message) {
440
+ return new Error(`@xylex-group/athena/cookies: ${message}`);
441
+ }
442
+ function getSecretOrThrow(secret) {
443
+ const resolved = secret || getEnvironmentSecret();
444
+ if (!resolved) {
445
+ throw createError(
446
+ "getCookieCache requires a secret. Pass `secret` or set ATHENA_AUTH_SECRET/BETTER_AUTH_SECRET/AUTH_SECRET."
447
+ );
448
+ }
449
+ return resolved;
450
+ }
451
+ function asObject(value) {
452
+ if (!value || typeof value !== "object") {
453
+ return null;
454
+ }
455
+ return value;
456
+ }
457
+ function getSessionTokenFromPair(session) {
458
+ const token = session.session?.token;
459
+ if (typeof token !== "string" || token.length === 0) {
460
+ throw createError("setSessionCookie requires `session.session.token` to be a non-empty string.");
461
+ }
462
+ return token;
463
+ }
464
+ async function resolveCookieVersion(versionConfig, session, user) {
465
+ if (!versionConfig) {
466
+ return "1";
467
+ }
468
+ if (typeof versionConfig === "string") {
469
+ return versionConfig;
470
+ }
471
+ return versionConfig(session, user);
472
+ }
473
+ function getSessionCookieCacheName(cookiePrefix, cookieName, isSecure) {
474
+ return isSecure ? `${SECURE_COOKIE_PREFIX}${cookiePrefix}.${cookieName}` : `${cookiePrefix}.${cookieName}`;
475
+ }
476
+ async function setCookieValue(ctx, name, value, attributes) {
477
+ const secret = ctx.context.secret;
478
+ if (secret && typeof ctx.setSignedCookie === "function") {
479
+ await ctx.setSignedCookie(name, value, secret, attributes);
480
+ return;
481
+ }
482
+ ctx.setCookie(name, value, attributes);
483
+ }
484
+ function parseJsonSafely(value) {
485
+ try {
486
+ return JSON.parse(value);
487
+ } catch {
488
+ return null;
489
+ }
490
+ }
491
+ function getIsSecureCookie(config) {
492
+ if (config?.isSecure !== void 0) {
493
+ return config.isSecure;
494
+ }
495
+ return isProductionRuntime();
496
+ }
497
+ function createCookieGetter(options) {
498
+ const baseURLString = typeof options.baseURL === "string" ? options.baseURL : void 0;
499
+ const dynamicProtocol = typeof options.baseURL === "object" && options.baseURL !== null ? options.baseURL.protocol : void 0;
500
+ const secure = options.advanced?.useSecureCookies !== void 0 ? options.advanced.useSecureCookies : dynamicProtocol === "https" ? true : dynamicProtocol === "http" ? false : baseURLString ? baseURLString.startsWith("https://") : isProductionRuntime();
501
+ const secureCookiePrefix = secure ? SECURE_COOKIE_PREFIX : "";
502
+ const crossSubdomainEnabled = !!options.advanced?.crossSubDomainCookies?.enabled;
503
+ const domain = crossSubdomainEnabled ? options.advanced?.crossSubDomainCookies?.domain || (baseURLString ? new URL(baseURLString).hostname : void 0) : void 0;
504
+ if (crossSubdomainEnabled && !domain && !isDynamicBaseURLConfig(options.baseURL)) {
505
+ throw createError("baseURL is required when `crossSubDomainCookies.enabled` is true.");
506
+ }
507
+ function createCookie(cookieName, overrideAttributes = {}) {
508
+ const prefix = options.advanced?.cookiePrefix || DEFAULT_COOKIE_PREFIX;
509
+ const name = options.advanced?.cookies?.[cookieName]?.name || `${prefix}.${cookieName}`;
510
+ const attributes = options.advanced?.cookies?.[cookieName]?.attributes || {};
511
+ return {
512
+ name: `${secureCookiePrefix}${name}`,
513
+ attributes: {
514
+ secure: !!secureCookiePrefix,
515
+ sameSite: "lax",
516
+ path: "/",
517
+ httpOnly: true,
518
+ ...crossSubdomainEnabled ? { domain } : {},
519
+ ...options.advanced?.defaultCookieAttributes,
520
+ ...overrideAttributes,
521
+ ...attributes
522
+ }
523
+ };
524
+ }
525
+ return createCookie;
526
+ }
527
+ function getCookies(options) {
528
+ const createCookie = createCookieGetter(options);
529
+ const sessionToken = createCookie("session_token", { maxAge: options.session?.expiresIn || DEFAULT_SESSION_MAX_AGE });
530
+ const sessionData = createCookie("session_data", { maxAge: options.session?.cookieCache?.maxAge || DEFAULT_CACHE_MAX_AGE });
531
+ const accountData = createCookie("account_data", { maxAge: options.session?.cookieCache?.maxAge || DEFAULT_CACHE_MAX_AGE });
532
+ const dontRememberToken = createCookie("dont_remember");
533
+ return {
534
+ sessionToken: {
535
+ name: sessionToken.name,
536
+ attributes: sessionToken.attributes
537
+ },
538
+ sessionData: {
539
+ name: sessionData.name,
540
+ attributes: sessionData.attributes
541
+ },
542
+ dontRememberToken: {
543
+ name: dontRememberToken.name,
544
+ attributes: dontRememberToken.attributes
545
+ },
546
+ accountData: {
547
+ name: accountData.name,
548
+ attributes: accountData.attributes
549
+ }
550
+ };
551
+ }
552
+ async function setCookieCache(ctx, session, dontRememberMe) {
553
+ const cookieCacheConfig = ctx.context.options?.session?.cookieCache;
554
+ if (!cookieCacheConfig?.enabled) {
555
+ return;
556
+ }
557
+ const version = await resolveCookieVersion(
558
+ cookieCacheConfig.version,
559
+ session.session,
560
+ session.user
561
+ );
562
+ const sessionData = {
563
+ session: session.session,
564
+ user: session.user,
565
+ updatedAt: Date.now(),
566
+ version
567
+ };
568
+ const baseAttributes = ctx.context.authCookies.sessionData.attributes;
569
+ const maxAge = dontRememberMe ? void 0 : baseAttributes.maxAge;
570
+ const options = {
571
+ ...baseAttributes,
572
+ maxAge
573
+ };
574
+ const expiresAt = Date.now() + (options.maxAge || 60) * 1e3;
575
+ const strategy = cookieCacheConfig.strategy || "compact";
576
+ const secret = getSecretOrThrow(ctx.context.secret);
577
+ let encoded;
578
+ if (strategy === "jwt") {
579
+ encoded = await signJwtHS256(sessionData, secret, options.maxAge || DEFAULT_CACHE_MAX_AGE);
580
+ } else if (strategy === "jwe") {
581
+ throw createError("`jwe` strategy is not supported by the SDK cookie helper.");
582
+ } else {
583
+ const signature = await signHmacBase64Url(
584
+ secret,
585
+ JSON.stringify({
586
+ ...sessionData,
587
+ expiresAt
588
+ })
589
+ );
590
+ encoded = encodeStringToBase64Url(
591
+ JSON.stringify({
592
+ session: sessionData,
593
+ expiresAt,
594
+ signature
595
+ })
596
+ );
597
+ }
598
+ if (encoded.length > 4093) {
599
+ const store = createSessionStore(ctx.context.authCookies.sessionData.name, options, ctx);
600
+ const cookies = store.chunk(encoded, options);
601
+ store.setCookies(cookies);
602
+ } else {
603
+ const store = createSessionStore(ctx.context.authCookies.sessionData.name, options, ctx);
604
+ if (store.hasChunks()) {
605
+ store.setCookies(store.clean());
606
+ }
607
+ ctx.setCookie(ctx.context.authCookies.sessionData.name, encoded, options);
608
+ }
609
+ }
610
+ async function setSessionCookie(ctx, session, dontRememberMe, overrides) {
611
+ if (dontRememberMe === void 0 && typeof ctx.getSignedCookie === "function" && ctx.context.secret) {
612
+ const existingFlag = await ctx.getSignedCookie(ctx.context.authCookies.dontRememberToken.name, ctx.context.secret);
613
+ dontRememberMe = !!existingFlag;
614
+ }
615
+ const resolvedDontRememberMe = dontRememberMe ?? false;
616
+ const token = getSessionTokenFromPair(session);
617
+ const options = ctx.context.authCookies.sessionToken.attributes;
618
+ const maxAge = resolvedDontRememberMe ? void 0 : ctx.context.sessionConfig?.expiresIn;
619
+ await setCookieValue(ctx, ctx.context.authCookies.sessionToken.name, token, {
620
+ ...options,
621
+ maxAge,
622
+ ...overrides
623
+ });
624
+ if (resolvedDontRememberMe) {
625
+ await setCookieValue(
626
+ ctx,
627
+ ctx.context.authCookies.dontRememberToken.name,
628
+ "true",
629
+ ctx.context.authCookies.dontRememberToken.attributes
630
+ );
631
+ }
632
+ await setCookieCache(ctx, session, resolvedDontRememberMe);
633
+ ctx.context.setNewSession?.(session);
634
+ }
635
+ function expireCookie(ctx, cookie) {
636
+ ctx.setCookie(cookie.name, "", {
637
+ ...cookie.attributes,
638
+ maxAge: 0
639
+ });
640
+ }
641
+ function deleteSessionCookie(ctx, skipDontRememberMe) {
642
+ expireCookie(ctx, ctx.context.authCookies.sessionToken);
643
+ expireCookie(ctx, ctx.context.authCookies.sessionData);
644
+ if (ctx.context.options?.account?.storeAccountCookie) {
645
+ expireCookie(ctx, ctx.context.authCookies.accountData);
646
+ const accountStore = createAccountStore(
647
+ ctx.context.authCookies.accountData.name,
648
+ ctx.context.authCookies.accountData.attributes,
649
+ ctx
650
+ );
651
+ accountStore.setCookies(accountStore.clean());
652
+ }
653
+ const sessionStore = createSessionStore(
654
+ ctx.context.authCookies.sessionData.name,
655
+ ctx.context.authCookies.sessionData.attributes,
656
+ ctx
657
+ );
658
+ sessionStore.setCookies(sessionStore.clean());
659
+ if (!skipDontRememberMe) {
660
+ expireCookie(ctx, ctx.context.authCookies.dontRememberToken);
661
+ }
662
+ }
663
+ var getSessionCookie = (request, config) => {
664
+ const cookies = (request instanceof Headers || !("headers" in request) ? request : request.headers).get("cookie");
665
+ if (!cookies) {
666
+ return null;
667
+ }
668
+ const { cookieName = "session_token", cookiePrefix = "athena-auth" } = config || {};
669
+ const parsedCookie = parseCookies(cookies);
670
+ const getCookie = (name) => parsedCookie.get(name) || parsedCookie.get(`${SECURE_COOKIE_PREFIX}${name}`);
671
+ const sessionToken = getCookie(`${cookiePrefix}.${cookieName}`) || getCookie(`${cookiePrefix}-${cookieName}`);
672
+ if (sessionToken) {
673
+ return sessionToken;
674
+ }
675
+ return null;
676
+ };
677
+ var getCookieCache = async (request, config) => {
678
+ const headers = request instanceof Headers || !("headers" in request) ? request : request.headers;
679
+ const cookieHeader = headers.get("cookie");
680
+ if (!cookieHeader) {
681
+ return null;
682
+ }
683
+ const parsedCookie = parseCookies(cookieHeader);
684
+ const cookieName = config?.cookieName || "session_data";
685
+ const requestedPrefix = config?.cookiePrefix || DEFAULT_COOKIE_PREFIX;
686
+ const strategy = config?.strategy || "compact";
687
+ const cookiePrefixes = resolveCookiePrefixes(requestedPrefix);
688
+ const isSecure = getIsSecureCookie(config);
689
+ const secret = getSecretOrThrow(config?.secret);
690
+ let sessionData;
691
+ for (const prefix of cookiePrefixes) {
692
+ const candidate = getSessionCookieCacheName(prefix, cookieName, isSecure);
693
+ const cookieValue = parsedCookie.get(candidate);
694
+ if (cookieValue) {
695
+ sessionData = cookieValue;
696
+ break;
697
+ }
698
+ }
699
+ if (!sessionData) {
700
+ const reconstructedChunks = [];
701
+ for (const prefix of cookiePrefixes) {
702
+ const candidate = getSessionCookieCacheName(prefix, cookieName, isSecure);
703
+ for (const [name, value] of parsedCookie.entries()) {
704
+ if (!name.startsWith(`${candidate}.`)) {
705
+ continue;
706
+ }
707
+ const parts = name.split(".");
708
+ const indexStr = parts[parts.length - 1];
709
+ const index = parseInt(indexStr || "0", 10);
710
+ if (!Number.isNaN(index)) {
711
+ reconstructedChunks.push({ index, value });
712
+ }
713
+ }
714
+ if (reconstructedChunks.length > 0) {
715
+ break;
716
+ }
717
+ }
718
+ if (reconstructedChunks.length > 0) {
719
+ reconstructedChunks.sort((left, right) => left.index - right.index);
720
+ sessionData = reconstructedChunks.map((chunk) => chunk.value).join("");
721
+ }
722
+ }
723
+ if (!sessionData) {
724
+ return null;
725
+ }
726
+ if (strategy === "jwe") {
727
+ throw createError(
728
+ "`jwe` strategy is not supported by the SDK cookie helper. Use compact/jwt or pass cookie data through the auth server."
729
+ );
730
+ }
731
+ if (strategy === "jwt") {
732
+ const payload = await verifyJwtHS256(sessionData, secret);
733
+ if (!payload) {
734
+ return null;
735
+ }
736
+ const sessionRecord = asObject(payload.session);
737
+ const userRecord = asObject(payload.user);
738
+ const updatedAt = payload.updatedAt;
739
+ if (!sessionRecord || !userRecord || typeof updatedAt !== "number") {
740
+ return null;
741
+ }
742
+ if (config?.version) {
743
+ const cookieVersion = typeof payload.version === "string" ? payload.version : "1";
744
+ const expectedVersion = typeof config.version === "string" ? config.version : await config.version(sessionRecord, userRecord);
745
+ if (cookieVersion !== expectedVersion) {
746
+ return null;
747
+ }
748
+ }
749
+ return {
750
+ session: sessionRecord,
751
+ user: userRecord,
752
+ updatedAt,
753
+ version: typeof payload.version === "string" ? payload.version : void 0
754
+ };
755
+ }
756
+ const compactPayload = parseJsonSafely(decodeBase64UrlToString(sessionData));
757
+ if (!compactPayload) {
758
+ return null;
759
+ }
760
+ const expectedSignature = await signHmacBase64Url(
761
+ secret,
762
+ JSON.stringify({
763
+ ...compactPayload.session,
764
+ expiresAt: compactPayload.expiresAt
765
+ })
766
+ );
767
+ if (expectedSignature !== compactPayload.signature) {
768
+ return null;
769
+ }
770
+ if (compactPayload.expiresAt <= Date.now()) {
771
+ return null;
772
+ }
773
+ const resolvedSession = compactPayload.session;
774
+ if (config?.version) {
775
+ const cookieVersion = resolvedSession.version || "1";
776
+ const expectedVersion = typeof config.version === "string" ? config.version : await config.version(resolvedSession.session, resolvedSession.user);
777
+ if (cookieVersion !== expectedVersion) {
778
+ return null;
779
+ }
780
+ }
781
+ const sessionObject = asObject(resolvedSession.session);
782
+ const userObject = asObject(resolvedSession.user);
783
+ if (!sessionObject || !userObject) {
784
+ return null;
785
+ }
786
+ return {
787
+ session: sessionObject,
788
+ user: userObject,
789
+ updatedAt: resolvedSession.updatedAt,
790
+ version: resolvedSession.version
791
+ };
792
+ };
793
+
794
+ // package.json
795
+ var package_default = {
796
+ version: "2.6.0"
797
+ };
798
+
799
+ // src/sdk-version.ts
800
+ var PACKAGE_VERSION = package_default.version;
801
+ function buildSdkHeaderValue(sdkName) {
802
+ return `${sdkName} ${PACKAGE_VERSION}`;
803
+ }
804
+
130
805
  // src/gateway/client.ts
131
806
  var DEFAULT_CLIENT = "railway_direct";
132
- var FALLBACK_SDK_VERSION = "1.3.0";
133
807
  var SDK_NAME = "xylex-group/athena";
134
- var SDK_VERSION = typeof process !== "undefined" && process?.env?.npm_package_version ? process.env.npm_package_version : FALLBACK_SDK_VERSION;
135
- var SDK_HEADER_VALUE = `${SDK_NAME} ${SDK_VERSION}`;
808
+ var SDK_HEADER_VALUE = buildSdkHeaderValue(SDK_NAME);
136
809
  function parseResponseBody(rawText, contentType) {
137
810
  if (!rawText) {
138
811
  return { parsed: null, parseFailed: false };
@@ -151,6 +824,37 @@ function parseResponseBody(rawText, contentType) {
151
824
  function normalizeHeaderValue(value) {
152
825
  return value ? value : void 0;
153
826
  }
827
+ function resolveHeaderValue(headers, candidates) {
828
+ for (const candidate of candidates) {
829
+ const direct = normalizeHeaderValue(headers[candidate]);
830
+ if (direct) return direct;
831
+ }
832
+ const loweredCandidates = new Set(candidates.map((candidate) => candidate.toLowerCase()));
833
+ for (const [key, value] of Object.entries(headers)) {
834
+ if (!loweredCandidates.has(key.toLowerCase())) {
835
+ continue;
836
+ }
837
+ const normalized = normalizeHeaderValue(value);
838
+ if (normalized) return normalized;
839
+ }
840
+ return void 0;
841
+ }
842
+ function resolveBearerTokenFromAuthorizationHeader(headers) {
843
+ const authorization = resolveHeaderValue(headers, ["Authorization"]);
844
+ if (!authorization) {
845
+ return void 0;
846
+ }
847
+ const match = authorization.match(/^Bearer\s+(.+)$/i);
848
+ const token = match?.[1]?.trim();
849
+ return token ? token : void 0;
850
+ }
851
+ function resolveSessionTokenFromCookieHeader(headers) {
852
+ const cookie = resolveHeaderValue(headers, ["Cookie"]);
853
+ if (!cookie) {
854
+ return void 0;
855
+ }
856
+ return getSessionCookie(new Headers({ cookie })) ?? void 0;
857
+ }
154
858
  function isRecord(value) {
155
859
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
156
860
  }
@@ -268,7 +972,7 @@ function buildRpcGetEndpoint(payload) {
268
972
  status: 0
269
973
  });
270
974
  }
271
- query.set(filter.column, toRpcFilterQueryValue(filter));
975
+ query.append(filter.column, toRpcFilterQueryValue(filter));
272
976
  }
273
977
  }
274
978
  const endpoint = `/rpc/${encodeURIComponent(functionName)}`;
@@ -314,6 +1018,20 @@ function buildHeaders(config, options) {
314
1018
  headers["apikey"] = finalApiKey;
315
1019
  headers["x-api-key"] = headers["x-api-key"] ?? finalApiKey;
316
1020
  }
1021
+ const explicitSessionToken = resolveHeaderValue(extraHeaders, [
1022
+ "X-Athena-Auth-Session-Token"
1023
+ ]);
1024
+ const derivedSessionToken = explicitSessionToken ?? resolveSessionTokenFromCookieHeader(extraHeaders);
1025
+ if (derivedSessionToken) {
1026
+ headers["X-Athena-Auth-Session-Token"] = derivedSessionToken;
1027
+ }
1028
+ const explicitBearerToken = resolveHeaderValue(extraHeaders, [
1029
+ "X-Athena-Auth-Bearer-Token"
1030
+ ]);
1031
+ const derivedBearerToken = explicitBearerToken ?? resolveBearerTokenFromAuthorizationHeader(extraHeaders);
1032
+ if (derivedBearerToken) {
1033
+ headers["X-Athena-Auth-Bearer-Token"] = derivedBearerToken;
1034
+ }
317
1035
  const athenaClientKeys = ["x-athena-client", "X-Athena-Client"];
318
1036
  Object.entries(extraHeaders).forEach(([key, value]) => {
319
1037
  if (athenaClientKeys.includes(key)) return;
@@ -1009,10 +1727,8 @@ async function resolveReactEmailPayloadFields(input, fields, options) {
1009
1727
 
1010
1728
  // src/auth/client.ts
1011
1729
  var DEFAULT_AUTH_BASE_URL = "http://localhost:3001/api/auth";
1012
- var FALLBACK_SDK_VERSION2 = "1.0.0";
1013
1730
  var SDK_NAME2 = "xylex-group/athena-auth";
1014
- var SDK_VERSION2 = typeof process !== "undefined" && process?.env?.npm_package_version ? process.env.npm_package_version : FALLBACK_SDK_VERSION2;
1015
- var SDK_HEADER_VALUE2 = `${SDK_NAME2} ${SDK_VERSION2}`;
1731
+ var SDK_HEADER_VALUE2 = buildSdkHeaderValue(SDK_NAME2);
1016
1732
  function normalizeBaseUrl(baseUrl) {
1017
1733
  return (baseUrl ?? DEFAULT_AUTH_BASE_URL).replace(/\/$/, "");
1018
1734
  }
@@ -2652,47 +3368,739 @@ function createDbModule(input) {
2652
3368
  return db;
2653
3369
  }
2654
3370
 
2655
- // src/query-ast.ts
2656
- var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
2657
- var FILTER_OPERATORS = /* @__PURE__ */ new Set([
2658
- "eq",
2659
- "neq",
2660
- "gt",
2661
- "gte",
2662
- "lt",
2663
- "lte",
2664
- "like",
2665
- "ilike",
2666
- "is",
2667
- "in",
2668
- "contains",
2669
- "containedBy"
2670
- ]);
2671
- var BOOLEAN_SAFE_OPERATORS = /* @__PURE__ */ new Set([
2672
- "eq",
2673
- "neq",
2674
- "gt",
2675
- "gte",
2676
- "lt",
2677
- "lte",
2678
- "like",
2679
- "ilike",
2680
- "is"
2681
- ]);
2682
- function isRecord5(value) {
2683
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
2684
- }
2685
- function isUuidString(value) {
2686
- return UUID_PATTERN.test(value.trim());
2687
- }
2688
- function isUuidIdentifierColumn(column) {
2689
- return column === "id" || /(?:^|_)uuid(?:_|$)/i.test(column) || /_id$/i.test(column);
2690
- }
2691
- function shouldUseUuidTextComparison(column, value) {
2692
- return typeof value === "string" && isUuidString(value) && isUuidIdentifierColumn(column);
2693
- }
2694
- function isRelationSelectNode(value) {
2695
- return isRecord5(value) && isRecord5(value.select);
3371
+ // src/storage/module.ts
3372
+ var storageSdkManifest = {
3373
+ namespace: "storage",
3374
+ basePath: "/storage",
3375
+ envelopeKinds: {
3376
+ raw: "response body is the payload",
3377
+ athena: "response body is { status, message, data }"
3378
+ },
3379
+ methods: [
3380
+ {
3381
+ name: "listStorageCatalogs",
3382
+ method: "GET",
3383
+ path: "/storage/catalogs",
3384
+ responseEnvelope: "raw",
3385
+ responseType: "{ data: S3CatalogItem[] }"
3386
+ },
3387
+ {
3388
+ name: "createStorageCatalog",
3389
+ method: "POST",
3390
+ path: "/storage/catalogs",
3391
+ requestType: "CreateStorageCatalogRequest",
3392
+ responseEnvelope: "raw",
3393
+ responseType: "S3CatalogItem"
3394
+ },
3395
+ {
3396
+ name: "updateStorageCatalog",
3397
+ method: "PATCH",
3398
+ path: "/storage/catalogs/{id}",
3399
+ pathParams: ["id"],
3400
+ requestType: "UpdateStorageCatalogRequest",
3401
+ responseEnvelope: "raw",
3402
+ responseType: "S3CatalogItem"
3403
+ },
3404
+ {
3405
+ name: "deleteStorageCatalog",
3406
+ method: "DELETE",
3407
+ path: "/storage/catalogs/{id}",
3408
+ pathParams: ["id"],
3409
+ responseEnvelope: "raw",
3410
+ responseType: "{ id: string; deleted: boolean }"
3411
+ },
3412
+ {
3413
+ name: "listStorageCredentials",
3414
+ method: "GET",
3415
+ path: "/storage/credentials",
3416
+ responseEnvelope: "raw",
3417
+ responseType: "{ data: S3CredentialListItem[] }"
3418
+ },
3419
+ {
3420
+ name: "createStorageUploadUrl",
3421
+ method: "POST",
3422
+ path: "/storage/files/upload-url",
3423
+ requestType: "CreateStorageUploadUrlRequest",
3424
+ responseEnvelope: "athena",
3425
+ responseType: "StorageUploadUrlResponse"
3426
+ },
3427
+ {
3428
+ name: "createStorageUploadUrls",
3429
+ method: "POST",
3430
+ path: "/storage/files/upload-urls",
3431
+ requestType: "CreateStorageUploadUrlsRequest",
3432
+ responseEnvelope: "athena",
3433
+ responseType: "StorageBatchUploadUrlResponse"
3434
+ },
3435
+ {
3436
+ name: "listStorageFiles",
3437
+ method: "POST",
3438
+ path: "/storage/files/list",
3439
+ requestType: "ListStorageFilesRequest",
3440
+ responseEnvelope: "athena",
3441
+ responseType: "StorageListFilesResponse"
3442
+ },
3443
+ {
3444
+ name: "getStorageFile",
3445
+ method: "GET",
3446
+ path: "/storage/files/{file_id}",
3447
+ pathParams: ["file_id"],
3448
+ responseEnvelope: "athena",
3449
+ responseType: "StorageFileMutationResponse"
3450
+ },
3451
+ {
3452
+ name: "getStorageFileUrl",
3453
+ method: "GET",
3454
+ path: "/storage/files/{file_id}/url",
3455
+ pathParams: ["file_id"],
3456
+ queryParams: ["purpose"],
3457
+ responseEnvelope: "athena",
3458
+ responseType: "PresignedFileUrlResponse"
3459
+ },
3460
+ {
3461
+ name: "getStorageFileProxy",
3462
+ method: "GET",
3463
+ path: "/storage/files/{file_id}/proxy",
3464
+ pathParams: ["file_id"],
3465
+ queryParams: ["purpose"],
3466
+ responseEnvelope: "raw",
3467
+ responseType: "Response",
3468
+ binary: true
3469
+ },
3470
+ {
3471
+ name: "updateStorageFile",
3472
+ method: "PATCH",
3473
+ path: "/storage/files/{file_id}",
3474
+ pathParams: ["file_id"],
3475
+ requestType: "UpdateStorageFileRequest",
3476
+ responseEnvelope: "athena",
3477
+ responseType: "StorageFileMutationResponse"
3478
+ },
3479
+ {
3480
+ name: "deleteStorageFile",
3481
+ method: "DELETE",
3482
+ path: "/storage/files/{file_id}",
3483
+ pathParams: ["file_id"],
3484
+ responseEnvelope: "athena",
3485
+ responseType: "StorageFileMutationResponse"
3486
+ },
3487
+ {
3488
+ name: "setStorageFileVisibility",
3489
+ method: "PATCH",
3490
+ path: "/storage/files/{file_id}/visibility",
3491
+ pathParams: ["file_id"],
3492
+ requestType: "SetStorageFileVisibilityRequest",
3493
+ responseEnvelope: "athena",
3494
+ responseType: "StorageFileMutationResponse"
3495
+ },
3496
+ {
3497
+ name: "deleteStorageFolder",
3498
+ method: "POST",
3499
+ path: "/storage/folders/delete",
3500
+ requestType: "DeleteStorageFolderRequest",
3501
+ responseEnvelope: "athena",
3502
+ responseType: "StorageFolderMutationResponse"
3503
+ },
3504
+ {
3505
+ name: "moveStorageFolder",
3506
+ method: "POST",
3507
+ path: "/storage/folders/move",
3508
+ requestType: "MoveStorageFolderRequest",
3509
+ responseEnvelope: "athena",
3510
+ responseType: "StorageFolderMutationResponse"
3511
+ }
3512
+ ]
3513
+ };
3514
+ var AthenaStorageErrorCode = {
3515
+ InvalidUrl: "INVALID_URL",
3516
+ NetworkError: "NETWORK_ERROR",
3517
+ HttpError: "HTTP_ERROR",
3518
+ InvalidJson: "INVALID_JSON",
3519
+ InvalidAthenaEnvelope: "INVALID_ATHENA_ENVELOPE",
3520
+ UnknownError: "UNKNOWN_ERROR"
3521
+ };
3522
+ var AthenaStorageError = class extends Error {
3523
+ code;
3524
+ athenaCode;
3525
+ kind;
3526
+ category;
3527
+ retryable;
3528
+ status;
3529
+ endpoint;
3530
+ method;
3531
+ requestId;
3532
+ hint;
3533
+ causeDetail;
3534
+ raw;
3535
+ normalized;
3536
+ __athenaNormalizedError;
3537
+ constructor(input) {
3538
+ super(input.message, { cause: input.cause });
3539
+ this.name = "AthenaStorageError";
3540
+ this.code = input.code;
3541
+ this.status = input.status;
3542
+ this.endpoint = input.endpoint;
3543
+ this.method = input.method;
3544
+ this.requestId = input.requestId;
3545
+ this.hint = input.hint;
3546
+ this.causeDetail = causeToString(input.cause);
3547
+ this.raw = input.raw ?? null;
3548
+ this.normalized = normalizeStorageErrorInput(input);
3549
+ this.__athenaNormalizedError = this.normalized;
3550
+ this.athenaCode = this.normalized.code;
3551
+ this.kind = this.normalized.kind;
3552
+ this.category = this.normalized.category;
3553
+ this.retryable = this.normalized.retryable;
3554
+ Object.defineProperty(this, "__athenaNormalizedError", {
3555
+ value: this.normalized,
3556
+ enumerable: false,
3557
+ configurable: false,
3558
+ writable: false
3559
+ });
3560
+ }
3561
+ toDetails() {
3562
+ return {
3563
+ code: this.code,
3564
+ athenaCode: this.athenaCode,
3565
+ kind: this.kind,
3566
+ category: this.category,
3567
+ retryable: this.retryable,
3568
+ message: this.message,
3569
+ status: this.status,
3570
+ endpoint: this.endpoint,
3571
+ method: this.method,
3572
+ requestId: this.requestId,
3573
+ hint: this.hint,
3574
+ cause: this.causeDetail,
3575
+ raw: this.raw
3576
+ };
3577
+ }
3578
+ };
3579
+ function isRecord5(value) {
3580
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
3581
+ }
3582
+ function causeToString(cause) {
3583
+ if (cause === void 0 || cause === null) return void 0;
3584
+ if (typeof cause === "string") return cause;
3585
+ if (cause instanceof Error && cause.message.trim()) return cause.message.trim();
3586
+ try {
3587
+ return JSON.stringify(cause);
3588
+ } catch {
3589
+ return String(cause);
3590
+ }
3591
+ }
3592
+ function storageGatewayCode(code) {
3593
+ if (code === "INVALID_URL") return "INVALID_URL";
3594
+ if (code === "NETWORK_ERROR") return "NETWORK_ERROR";
3595
+ if (code === "INVALID_JSON" || code === "INVALID_ATHENA_ENVELOPE") return "INVALID_JSON";
3596
+ if (code === "HTTP_ERROR") return "HTTP_ERROR";
3597
+ return "UNKNOWN_ERROR";
3598
+ }
3599
+ function headerValue(headers, names) {
3600
+ for (const name of names) {
3601
+ const value = headers.get(name);
3602
+ if (value?.trim()) return value.trim();
3603
+ }
3604
+ return void 0;
3605
+ }
3606
+ function storageOperationFromEndpoint(endpoint, method) {
3607
+ const endpointPath = String(endpoint).split("?")[0];
3608
+ for (const candidate of storageSdkManifest.methods) {
3609
+ if (candidate.method !== method) continue;
3610
+ const pattern = `^${candidate.path.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\\\{[^/]+\\\}/g, "[^/]+")}$`;
3611
+ if (new RegExp(pattern).test(endpointPath)) {
3612
+ return candidate.name;
3613
+ }
3614
+ }
3615
+ return `storage:${method.toLowerCase()}`;
3616
+ }
3617
+ function normalizeStorageErrorInput(input) {
3618
+ return normalizeAthenaError(
3619
+ {
3620
+ data: null,
3621
+ error: {
3622
+ message: input.message,
3623
+ gatewayCode: storageGatewayCode(input.code),
3624
+ status: input.status,
3625
+ raw: input.raw ?? input.cause ?? null
3626
+ },
3627
+ errorDetails: {
3628
+ code: storageGatewayCode(input.code),
3629
+ message: input.message,
3630
+ status: input.status,
3631
+ endpoint: input.endpoint,
3632
+ method: input.method,
3633
+ requestId: input.requestId,
3634
+ hint: input.hint,
3635
+ cause: causeToString(input.cause)
3636
+ },
3637
+ raw: input.raw ?? input.cause ?? null,
3638
+ status: input.status
3639
+ },
3640
+ { operation: storageOperationFromEndpoint(input.endpoint, input.method) }
3641
+ );
3642
+ }
3643
+ function createAthenaStorageError(input) {
3644
+ return new AthenaStorageError(input);
3645
+ }
3646
+ async function notifyStorageError(error, options, runtimeOptions) {
3647
+ const handlers = [runtimeOptions?.onError, options?.onError].filter(
3648
+ (handler) => typeof handler === "function"
3649
+ );
3650
+ for (const handler of handlers) {
3651
+ try {
3652
+ await handler(error);
3653
+ } catch {
3654
+ }
3655
+ }
3656
+ }
3657
+ async function rejectStorageError(input, options, runtimeOptions) {
3658
+ const error = createAthenaStorageError(input);
3659
+ await notifyStorageError(error, options, runtimeOptions);
3660
+ throw error;
3661
+ }
3662
+ function parseResponseBody3(rawText, contentType) {
3663
+ if (!rawText) {
3664
+ return { parsed: null, parseFailed: false };
3665
+ }
3666
+ const contentTypeSuggestsJson = contentType?.toLowerCase().includes("application/json") ?? false;
3667
+ const looksJson = contentTypeSuggestsJson || rawText.startsWith("{") || rawText.startsWith("[");
3668
+ if (!looksJson) {
3669
+ return { parsed: rawText, parseFailed: false };
3670
+ }
3671
+ try {
3672
+ return { parsed: JSON.parse(rawText), parseFailed: false };
3673
+ } catch {
3674
+ return { parsed: rawText, parseFailed: true };
3675
+ }
3676
+ }
3677
+ function appendQuery(path, query) {
3678
+ if (!query) return path;
3679
+ const params = new URLSearchParams();
3680
+ for (const [key, value] of Object.entries(query)) {
3681
+ if (value === void 0 || value === null) continue;
3682
+ params.set(key, String(value));
3683
+ }
3684
+ const queryText = params.toString();
3685
+ return queryText ? `${path}?${queryText}` : path;
3686
+ }
3687
+ function storagePath(path) {
3688
+ return path;
3689
+ }
3690
+ function withPathParam(path, name, value) {
3691
+ return path.replace(`{${name}}`, encodeURIComponent(value));
3692
+ }
3693
+ function resolveErrorMessage3(payload, fallback) {
3694
+ if (isRecord5(payload)) {
3695
+ const message = payload.message ?? payload.error ?? payload.details;
3696
+ if (typeof message === "string" && message.trim()) {
3697
+ return message.trim();
3698
+ }
3699
+ }
3700
+ if (typeof payload === "string" && payload.trim()) {
3701
+ return payload.trim();
3702
+ }
3703
+ return fallback;
3704
+ }
3705
+ function resolveErrorHint2(payload) {
3706
+ if (!isRecord5(payload)) return void 0;
3707
+ const hint = payload.hint ?? payload.suggestion;
3708
+ return typeof hint === "string" && hint.trim() ? hint.trim() : void 0;
3709
+ }
3710
+ function resolveErrorCause(payload) {
3711
+ if (!isRecord5(payload)) return void 0;
3712
+ const cause = payload.cause ?? payload.reason;
3713
+ return typeof cause === "string" && cause.trim() ? cause.trim() : void 0;
3714
+ }
3715
+ function storageCodeFromUnknown(error) {
3716
+ if (isAthenaGatewayError(error)) {
3717
+ if (error.code === "INVALID_URL") return "INVALID_URL";
3718
+ if (error.code === "NETWORK_ERROR") return "NETWORK_ERROR";
3719
+ if (error.code === "INVALID_JSON") return "INVALID_JSON";
3720
+ if (error.code === "HTTP_ERROR") return "HTTP_ERROR";
3721
+ }
3722
+ return "UNKNOWN_ERROR";
3723
+ }
3724
+ async function callStorageEndpoint(gateway, endpoint, method, envelope, payload, options, runtimeOptions) {
3725
+ let url;
3726
+ let headers;
3727
+ try {
3728
+ const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : gateway.baseUrl;
3729
+ url = buildAthenaGatewayUrl(baseUrl, endpoint);
3730
+ headers = gateway.buildHeaders(options);
3731
+ } catch (error) {
3732
+ return rejectStorageError(
3733
+ {
3734
+ code: storageCodeFromUnknown(error),
3735
+ message: error instanceof Error ? error.message : `Athena storage ${method} ${endpoint} failed before sending the request`,
3736
+ status: isAthenaGatewayError(error) ? error.status : 0,
3737
+ endpoint,
3738
+ method,
3739
+ raw: error,
3740
+ requestId: isAthenaGatewayError(error) ? error.requestId : void 0,
3741
+ hint: isAthenaGatewayError(error) ? error.hint : void 0,
3742
+ cause: error
3743
+ },
3744
+ options,
3745
+ runtimeOptions
3746
+ );
3747
+ }
3748
+ const requestInit = {
3749
+ method,
3750
+ headers,
3751
+ signal: options?.signal
3752
+ };
3753
+ if (payload !== void 0 && method !== "GET") {
3754
+ requestInit.body = JSON.stringify(payload);
3755
+ }
3756
+ let response;
3757
+ try {
3758
+ response = await fetch(url, requestInit);
3759
+ } catch (error) {
3760
+ const message = error instanceof Error ? error.message : String(error);
3761
+ return rejectStorageError(
3762
+ {
3763
+ code: "NETWORK_ERROR",
3764
+ message: `Network error while calling Athena storage ${method} ${endpoint}: ${message}`,
3765
+ status: 0,
3766
+ endpoint,
3767
+ method,
3768
+ cause: error
3769
+ },
3770
+ options,
3771
+ runtimeOptions
3772
+ );
3773
+ }
3774
+ let rawText;
3775
+ try {
3776
+ rawText = await response.text();
3777
+ } catch (error) {
3778
+ return rejectStorageError(
3779
+ {
3780
+ code: "NETWORK_ERROR",
3781
+ message: `Athena storage ${method} ${endpoint} response body could not be read`,
3782
+ status: response.status,
3783
+ endpoint,
3784
+ method,
3785
+ requestId: headerValue(response.headers, ["x-athena-request-id", "x-request-id", "request-id"]),
3786
+ cause: error
3787
+ },
3788
+ options,
3789
+ runtimeOptions
3790
+ );
3791
+ }
3792
+ const parsedBody = parseResponseBody3(rawText ?? "", response.headers.get("content-type"));
3793
+ const requestId = headerValue(response.headers, ["x-athena-request-id", "x-request-id", "request-id"]);
3794
+ if (parsedBody.parseFailed) {
3795
+ return rejectStorageError(
3796
+ {
3797
+ code: "INVALID_JSON",
3798
+ message: `Athena storage ${method} ${endpoint} returned malformed JSON`,
3799
+ status: response.status,
3800
+ endpoint,
3801
+ method,
3802
+ requestId,
3803
+ raw: parsedBody.parsed
3804
+ },
3805
+ options,
3806
+ runtimeOptions
3807
+ );
3808
+ }
3809
+ if (!response.ok) {
3810
+ return rejectStorageError(
3811
+ {
3812
+ code: "HTTP_ERROR",
3813
+ message: resolveErrorMessage3(
3814
+ parsedBody.parsed,
3815
+ `Athena storage ${method} ${endpoint} failed with status ${response.status}`
3816
+ ),
3817
+ status: response.status,
3818
+ endpoint,
3819
+ method,
3820
+ requestId,
3821
+ hint: resolveErrorHint2(parsedBody.parsed),
3822
+ cause: resolveErrorCause(parsedBody.parsed),
3823
+ raw: parsedBody.parsed
3824
+ },
3825
+ options,
3826
+ runtimeOptions
3827
+ );
3828
+ }
3829
+ if (envelope === "athena") {
3830
+ if (!isRecord5(parsedBody.parsed) || !("data" in parsedBody.parsed)) {
3831
+ return rejectStorageError(
3832
+ {
3833
+ code: "INVALID_ATHENA_ENVELOPE",
3834
+ message: `Athena storage ${method} ${endpoint} returned an invalid Athena envelope`,
3835
+ status: response.status,
3836
+ endpoint,
3837
+ method,
3838
+ requestId,
3839
+ raw: parsedBody.parsed
3840
+ },
3841
+ options,
3842
+ runtimeOptions
3843
+ );
3844
+ }
3845
+ return parsedBody.parsed.data;
3846
+ }
3847
+ return parsedBody.parsed;
3848
+ }
3849
+ async function callStorageBinaryEndpoint(gateway, endpoint, method, options, runtimeOptions) {
3850
+ let url;
3851
+ let headers;
3852
+ try {
3853
+ const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : gateway.baseUrl;
3854
+ url = buildAthenaGatewayUrl(baseUrl, endpoint);
3855
+ headers = gateway.buildHeaders(options);
3856
+ } catch (error) {
3857
+ return rejectStorageError(
3858
+ {
3859
+ code: storageCodeFromUnknown(error),
3860
+ message: error instanceof Error ? error.message : `Athena storage ${method} ${endpoint} failed before sending the request`,
3861
+ status: isAthenaGatewayError(error) ? error.status : 0,
3862
+ endpoint,
3863
+ method,
3864
+ raw: error,
3865
+ requestId: isAthenaGatewayError(error) ? error.requestId : void 0,
3866
+ hint: isAthenaGatewayError(error) ? error.hint : void 0,
3867
+ cause: error
3868
+ },
3869
+ options,
3870
+ runtimeOptions
3871
+ );
3872
+ }
3873
+ let response;
3874
+ try {
3875
+ response = await fetch(url, {
3876
+ method,
3877
+ headers,
3878
+ signal: options?.signal
3879
+ });
3880
+ } catch (error) {
3881
+ const message = error instanceof Error ? error.message : String(error);
3882
+ return rejectStorageError(
3883
+ {
3884
+ code: "NETWORK_ERROR",
3885
+ message: `Network error while calling Athena storage ${method} ${endpoint}: ${message}`,
3886
+ status: 0,
3887
+ endpoint,
3888
+ method,
3889
+ cause: error
3890
+ },
3891
+ options,
3892
+ runtimeOptions
3893
+ );
3894
+ }
3895
+ if (response.ok) {
3896
+ return response;
3897
+ }
3898
+ const requestId = headerValue(response.headers, ["x-athena-request-id", "x-request-id", "request-id"]);
3899
+ let rawErrorBody = null;
3900
+ try {
3901
+ const rawText = await response.text();
3902
+ const parsedBody = parseResponseBody3(rawText ?? "", response.headers.get("content-type"));
3903
+ rawErrorBody = parsedBody.parsed;
3904
+ } catch (error) {
3905
+ return rejectStorageError(
3906
+ {
3907
+ code: "NETWORK_ERROR",
3908
+ message: `Athena storage ${method} ${endpoint} error response body could not be read`,
3909
+ status: response.status,
3910
+ endpoint,
3911
+ method,
3912
+ requestId,
3913
+ cause: error
3914
+ },
3915
+ options,
3916
+ runtimeOptions
3917
+ );
3918
+ }
3919
+ return rejectStorageError(
3920
+ {
3921
+ code: "HTTP_ERROR",
3922
+ message: resolveErrorMessage3(
3923
+ rawErrorBody,
3924
+ `Athena storage ${method} ${endpoint} failed with status ${response.status}`
3925
+ ),
3926
+ status: response.status,
3927
+ endpoint,
3928
+ method,
3929
+ requestId,
3930
+ hint: resolveErrorHint2(rawErrorBody),
3931
+ cause: resolveErrorCause(rawErrorBody),
3932
+ raw: rawErrorBody
3933
+ },
3934
+ options,
3935
+ runtimeOptions
3936
+ );
3937
+ }
3938
+ function createStorageModule(gateway, runtimeOptions) {
3939
+ return {
3940
+ listStorageCatalogs(options) {
3941
+ return callStorageEndpoint(gateway, storagePath("/storage/catalogs"), "GET", "raw", void 0, options, runtimeOptions);
3942
+ },
3943
+ createStorageCatalog(input, options) {
3944
+ return callStorageEndpoint(gateway, storagePath("/storage/catalogs"), "POST", "raw", input, options, runtimeOptions);
3945
+ },
3946
+ updateStorageCatalog(id, input, options) {
3947
+ return callStorageEndpoint(
3948
+ gateway,
3949
+ storagePath(withPathParam("/storage/catalogs/{id}", "id", id)),
3950
+ "PATCH",
3951
+ "raw",
3952
+ input,
3953
+ options,
3954
+ runtimeOptions
3955
+ );
3956
+ },
3957
+ deleteStorageCatalog(id, options) {
3958
+ return callStorageEndpoint(
3959
+ gateway,
3960
+ storagePath(withPathParam("/storage/catalogs/{id}", "id", id)),
3961
+ "DELETE",
3962
+ "raw",
3963
+ void 0,
3964
+ options,
3965
+ runtimeOptions
3966
+ );
3967
+ },
3968
+ listStorageCredentials(options) {
3969
+ return callStorageEndpoint(gateway, storagePath("/storage/credentials"), "GET", "raw", void 0, options, runtimeOptions);
3970
+ },
3971
+ createStorageUploadUrl(input, options) {
3972
+ return callStorageEndpoint(
3973
+ gateway,
3974
+ storagePath("/storage/files/upload-url"),
3975
+ "POST",
3976
+ "athena",
3977
+ input,
3978
+ options,
3979
+ runtimeOptions
3980
+ );
3981
+ },
3982
+ createStorageUploadUrls(input, options) {
3983
+ return callStorageEndpoint(
3984
+ gateway,
3985
+ storagePath("/storage/files/upload-urls"),
3986
+ "POST",
3987
+ "athena",
3988
+ input,
3989
+ options,
3990
+ runtimeOptions
3991
+ );
3992
+ },
3993
+ listStorageFiles(input, options) {
3994
+ return callStorageEndpoint(gateway, storagePath("/storage/files/list"), "POST", "athena", input, options, runtimeOptions);
3995
+ },
3996
+ getStorageFile(fileId, options) {
3997
+ return callStorageEndpoint(
3998
+ gateway,
3999
+ storagePath(withPathParam("/storage/files/{file_id}", "file_id", fileId)),
4000
+ "GET",
4001
+ "athena",
4002
+ void 0,
4003
+ options,
4004
+ runtimeOptions
4005
+ );
4006
+ },
4007
+ getStorageFileUrl(fileId, query, options) {
4008
+ const path = appendQuery(
4009
+ withPathParam("/storage/files/{file_id}/url", "file_id", fileId),
4010
+ query
4011
+ );
4012
+ return callStorageEndpoint(gateway, storagePath(path), "GET", "athena", void 0, options, runtimeOptions);
4013
+ },
4014
+ getStorageFileProxy(fileId, query, options) {
4015
+ const path = appendQuery(
4016
+ withPathParam("/storage/files/{file_id}/proxy", "file_id", fileId),
4017
+ query
4018
+ );
4019
+ return callStorageBinaryEndpoint(gateway, storagePath(path), "GET", options, runtimeOptions);
4020
+ },
4021
+ updateStorageFile(fileId, input, options) {
4022
+ return callStorageEndpoint(
4023
+ gateway,
4024
+ storagePath(withPathParam("/storage/files/{file_id}", "file_id", fileId)),
4025
+ "PATCH",
4026
+ "athena",
4027
+ input,
4028
+ options,
4029
+ runtimeOptions
4030
+ );
4031
+ },
4032
+ deleteStorageFile(fileId, options) {
4033
+ return callStorageEndpoint(
4034
+ gateway,
4035
+ storagePath(withPathParam("/storage/files/{file_id}", "file_id", fileId)),
4036
+ "DELETE",
4037
+ "athena",
4038
+ void 0,
4039
+ options,
4040
+ runtimeOptions
4041
+ );
4042
+ },
4043
+ setStorageFileVisibility(fileId, input, options) {
4044
+ return callStorageEndpoint(
4045
+ gateway,
4046
+ storagePath(withPathParam("/storage/files/{file_id}/visibility", "file_id", fileId)),
4047
+ "PATCH",
4048
+ "athena",
4049
+ input,
4050
+ options,
4051
+ runtimeOptions
4052
+ );
4053
+ },
4054
+ deleteStorageFolder(input, options) {
4055
+ return callStorageEndpoint(gateway, storagePath("/storage/folders/delete"), "POST", "athena", input, options, runtimeOptions);
4056
+ },
4057
+ moveStorageFolder(input, options) {
4058
+ return callStorageEndpoint(gateway, storagePath("/storage/folders/move"), "POST", "athena", input, options, runtimeOptions);
4059
+ }
4060
+ };
4061
+ }
4062
+
4063
+ // src/query-ast.ts
4064
+ 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;
4065
+ var FILTER_OPERATORS = /* @__PURE__ */ new Set([
4066
+ "eq",
4067
+ "neq",
4068
+ "gt",
4069
+ "gte",
4070
+ "lt",
4071
+ "lte",
4072
+ "like",
4073
+ "ilike",
4074
+ "is",
4075
+ "in",
4076
+ "contains",
4077
+ "containedBy"
4078
+ ]);
4079
+ var BOOLEAN_SAFE_OPERATORS = /* @__PURE__ */ new Set([
4080
+ "eq",
4081
+ "neq",
4082
+ "gt",
4083
+ "gte",
4084
+ "lt",
4085
+ "lte",
4086
+ "like",
4087
+ "ilike",
4088
+ "is"
4089
+ ]);
4090
+ function isRecord6(value) {
4091
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
4092
+ }
4093
+ function isUuidString(value) {
4094
+ return UUID_PATTERN.test(value.trim());
4095
+ }
4096
+ function isUuidIdentifierColumn(column) {
4097
+ return column === "id" || /(?:^|_)uuid(?:_|$)/i.test(column) || /_id$/i.test(column);
4098
+ }
4099
+ function shouldUseUuidTextComparison(column, value) {
4100
+ return typeof value === "string" && isUuidString(value) && isUuidIdentifierColumn(column);
4101
+ }
4102
+ function isRelationSelectNode(value) {
4103
+ return isRecord6(value) && isRecord6(value.select);
2696
4104
  }
2697
4105
  function normalizeIdentifier(value, label) {
2698
4106
  const normalized = value.trim();
@@ -2748,7 +4156,7 @@ function compileRelationToken(key, node) {
2748
4156
  return `${prefix}${relationToken}(${nested})`;
2749
4157
  }
2750
4158
  function compileSelectShape(select) {
2751
- if (!isRecord5(select)) {
4159
+ if (!isRecord6(select)) {
2752
4160
  throw new Error("findMany select must be an object");
2753
4161
  }
2754
4162
  const tokens = [];
@@ -2772,7 +4180,7 @@ function compileSelectShape(select) {
2772
4180
  return tokens.join(",");
2773
4181
  }
2774
4182
  function selectShapeUsesRelationSchema(select) {
2775
- if (!isRecord5(select)) {
4183
+ if (!isRecord6(select)) {
2776
4184
  return false;
2777
4185
  }
2778
4186
  for (const rawValue of Object.values(select)) {
@@ -2790,7 +4198,7 @@ function selectShapeUsesRelationSchema(select) {
2790
4198
  }
2791
4199
  function compileColumnWhere(column, input) {
2792
4200
  const normalizedColumn = normalizeIdentifier(column, "where column");
2793
- if (!isRecord5(input)) {
4201
+ if (!isRecord6(input)) {
2794
4202
  return [buildGatewayCondition("eq", normalizedColumn, input)];
2795
4203
  }
2796
4204
  const conditions = [];
@@ -2818,7 +4226,7 @@ function compileColumnWhere(column, input) {
2818
4226
  return conditions;
2819
4227
  }
2820
4228
  function compileBooleanExpressionTerms(clause, label) {
2821
- if (!isRecord5(clause)) {
4229
+ if (!isRecord6(clause)) {
2822
4230
  throw new Error(`findMany where.${label} clauses must be objects`);
2823
4231
  }
2824
4232
  const entries = Object.entries(clause).filter(([, value]) => value !== void 0);
@@ -2827,7 +4235,7 @@ function compileBooleanExpressionTerms(clause, label) {
2827
4235
  }
2828
4236
  const [rawColumn, rawValue] = entries[0];
2829
4237
  const column = normalizeIdentifier(rawColumn, `where.${label} column`);
2830
- if (!isRecord5(rawValue)) {
4238
+ if (!isRecord6(rawValue)) {
2831
4239
  return [`${column}.eq.${stringifyFilterValue(rawValue)}`];
2832
4240
  }
2833
4241
  const operatorEntries = Object.entries(rawValue).filter(([, value]) => value !== void 0);
@@ -2851,7 +4259,7 @@ function compileWhere(where) {
2851
4259
  if (where === void 0) {
2852
4260
  return void 0;
2853
4261
  }
2854
- if (!isRecord5(where)) {
4262
+ if (!isRecord6(where)) {
2855
4263
  throw new Error("findMany where must be an object");
2856
4264
  }
2857
4265
  const conditions = [];
@@ -2901,7 +4309,7 @@ function compileOrderBy(orderBy) {
2901
4309
  if (orderBy === void 0) {
2902
4310
  return void 0;
2903
4311
  }
2904
- if (!isRecord5(orderBy)) {
4312
+ if (!isRecord6(orderBy)) {
2905
4313
  throw new Error("findMany orderBy must be an object");
2906
4314
  }
2907
4315
  if ("column" in orderBy) {
@@ -2997,7 +4405,7 @@ function buildStructuredWhere(conditions) {
2997
4405
  if (!condition.column) {
2998
4406
  return null;
2999
4407
  }
3000
- if (condition.column_cast !== void 0 || condition.value_cast !== void 0) {
4408
+ if (condition.value_cast !== void 0) {
3001
4409
  return null;
3002
4410
  }
3003
4411
  const operand = condition.value;
@@ -3076,6 +4484,104 @@ function toFindManyAstOrder(order) {
3076
4484
  ascending: order.direction !== "descending"
3077
4485
  };
3078
4486
  }
4487
+ function isRecord7(value) {
4488
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
4489
+ }
4490
+ function normalizeFindManyAstColumnPredicate(value) {
4491
+ if (!isRecord7(value)) {
4492
+ return {
4493
+ eq: value
4494
+ };
4495
+ }
4496
+ const normalized = {};
4497
+ for (const [key, operand] of Object.entries(value)) {
4498
+ if (operand !== void 0) {
4499
+ normalized[key] = operand;
4500
+ }
4501
+ }
4502
+ return normalized;
4503
+ }
4504
+ function normalizeFindManyAstBooleanOperand(clause) {
4505
+ const normalized = {};
4506
+ for (const [column, value] of Object.entries(clause)) {
4507
+ if (value === void 0) {
4508
+ continue;
4509
+ }
4510
+ normalized[column] = normalizeFindManyAstColumnPredicate(value);
4511
+ }
4512
+ return normalized;
4513
+ }
4514
+ function normalizeFindManyAstWhere(where) {
4515
+ if (!where || !isRecord7(where)) {
4516
+ return where;
4517
+ }
4518
+ const normalized = {};
4519
+ for (const [key, value] of Object.entries(where)) {
4520
+ if (value === void 0) {
4521
+ continue;
4522
+ }
4523
+ if (key === "or" && Array.isArray(value)) {
4524
+ normalized.or = value.map(
4525
+ (clause) => normalizeFindManyAstBooleanOperand(clause)
4526
+ );
4527
+ continue;
4528
+ }
4529
+ if (key === "not" && isRecord7(value)) {
4530
+ normalized.not = normalizeFindManyAstBooleanOperand(
4531
+ value
4532
+ );
4533
+ continue;
4534
+ }
4535
+ normalized[key] = normalizeFindManyAstColumnPredicate(value);
4536
+ }
4537
+ return normalized;
4538
+ }
4539
+ function predicateRequiresUuidQueryFallback(column, value) {
4540
+ if (!isRecord7(value)) {
4541
+ return shouldUseUuidTextComparison(column, value);
4542
+ }
4543
+ const eqValue = value.eq;
4544
+ return eqValue !== void 0 && shouldUseUuidTextComparison(column, eqValue);
4545
+ }
4546
+ function booleanOperandRequiresUuidQueryFallback(clause) {
4547
+ for (const [column, value] of Object.entries(clause)) {
4548
+ if (value === void 0) {
4549
+ continue;
4550
+ }
4551
+ if (predicateRequiresUuidQueryFallback(column, value)) {
4552
+ return true;
4553
+ }
4554
+ }
4555
+ return false;
4556
+ }
4557
+ function findManyAstWhereRequiresLegacyTransport(where) {
4558
+ if (!where || !isRecord7(where)) {
4559
+ return false;
4560
+ }
4561
+ for (const [key, value] of Object.entries(where)) {
4562
+ if (value === void 0) {
4563
+ continue;
4564
+ }
4565
+ if (key === "or" && Array.isArray(value)) {
4566
+ if (value.some(
4567
+ (clause) => booleanOperandRequiresUuidQueryFallback(clause)
4568
+ )) {
4569
+ return true;
4570
+ }
4571
+ continue;
4572
+ }
4573
+ if (key === "not" && isRecord7(value)) {
4574
+ if (booleanOperandRequiresUuidQueryFallback(value)) {
4575
+ return true;
4576
+ }
4577
+ continue;
4578
+ }
4579
+ if (predicateRequiresUuidQueryFallback(key, value)) {
4580
+ return true;
4581
+ }
4582
+ }
4583
+ return false;
4584
+ }
3079
4585
  function resolvePagination(input) {
3080
4586
  let limit = input.limit;
3081
4587
  let offset = input.offset;
@@ -3094,25 +4600,6 @@ function hasTypedEqualityComparison(conditions) {
3094
4600
  }
3095
4601
  function createSelectTransportPlan(input) {
3096
4602
  const conditions = input.state.conditions.length ? input.state.conditions.map((condition) => ({ ...condition })) : void 0;
3097
- if (hasTypedEqualityComparison(conditions) && !input.options?.head && !input.options?.count && conditions) {
3098
- const query = input.buildTypedSelectQuery({
3099
- tableName: input.tableName,
3100
- columns: input.columns,
3101
- conditions,
3102
- limit: input.state.limit,
3103
- offset: input.state.offset,
3104
- currentPage: input.state.currentPage,
3105
- pageSize: input.state.pageSize,
3106
- order: input.state.order
3107
- });
3108
- if (query) {
3109
- return {
3110
- kind: "query",
3111
- query,
3112
- payload: { query }
3113
- };
3114
- }
3115
- }
3116
4603
  const pagination = resolvePagination({
3117
4604
  limit: input.state.limit,
3118
4605
  offset: input.state.offset,
@@ -3148,6 +4635,25 @@ function createSelectTransportPlan(input) {
3148
4635
  }
3149
4636
  };
3150
4637
  }
4638
+ if (hasTypedEqualityComparison(conditions) && !input.options?.head && !input.options?.count && conditions) {
4639
+ const query = input.buildTypedSelectQuery({
4640
+ tableName: input.tableName,
4641
+ columns: input.columns,
4642
+ conditions,
4643
+ limit: input.state.limit,
4644
+ offset: input.state.offset,
4645
+ currentPage: input.state.currentPage,
4646
+ pageSize: input.state.pageSize,
4647
+ order: input.state.order
4648
+ });
4649
+ if (query) {
4650
+ return {
4651
+ kind: "query",
4652
+ query,
4653
+ payload: { query }
4654
+ };
4655
+ }
4656
+ }
3151
4657
  return {
3152
4658
  kind: "fetch",
3153
4659
  payload: {
@@ -3204,6 +4710,13 @@ function formatResult(response) {
3204
4710
  }
3205
4711
  return result;
3206
4712
  }
4713
+ var EXPERIMENTAL_READ_RETRY_CONFIG = {
4714
+ retries: 2,
4715
+ baseDelayMs: 100,
4716
+ maxDelayMs: 1e3,
4717
+ backoff: "exponential",
4718
+ jitter: true
4719
+ };
3207
4720
  function attachNormalizedError(result, normalizedError) {
3208
4721
  Object.defineProperty(result, ATHENA_NORMALIZED_ERROR_KEY, {
3209
4722
  value: normalizedError,
@@ -3230,7 +4743,36 @@ function createResultFormatter(experimental) {
3230
4743
  return result;
3231
4744
  };
3232
4745
  }
3233
- function isRecord6(value) {
4746
+ async function executeExperimentalRead(experimental, runner) {
4747
+ if (!experimental?.retryReads) {
4748
+ return runner();
4749
+ }
4750
+ let lastRetryableResult;
4751
+ let lastRetrySignal = null;
4752
+ try {
4753
+ return await withRetry(
4754
+ {
4755
+ ...EXPERIMENTAL_READ_RETRY_CONFIG,
4756
+ shouldRetry: (error) => error === lastRetrySignal || normalizeAthenaError(error).retryable
4757
+ },
4758
+ async () => {
4759
+ const result = await runner();
4760
+ if (result.error?.retryable) {
4761
+ lastRetryableResult = result;
4762
+ lastRetrySignal = result.error;
4763
+ throw lastRetrySignal;
4764
+ }
4765
+ return result;
4766
+ }
4767
+ );
4768
+ } catch (error) {
4769
+ if (lastRetryableResult && error === lastRetrySignal) {
4770
+ return lastRetryableResult;
4771
+ }
4772
+ throw error;
4773
+ }
4774
+ }
4775
+ function isRecord8(value) {
3234
4776
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
3235
4777
  }
3236
4778
  function firstNonEmptyString2(...values) {
@@ -3242,8 +4784,8 @@ function firstNonEmptyString2(...values) {
3242
4784
  return void 0;
3243
4785
  }
3244
4786
  function resolveStructuredErrorPayload2(raw) {
3245
- if (!isRecord6(raw)) return null;
3246
- return isRecord6(raw.error) ? raw.error : raw;
4787
+ if (!isRecord8(raw)) return null;
4788
+ return isRecord8(raw.error) ? raw.error : raw;
3247
4789
  }
3248
4790
  function resolveStructuredErrorDetails(payload, message) {
3249
4791
  if (!payload || !("details" in payload)) {
@@ -3259,7 +4801,7 @@ function resolveStructuredErrorDetails(payload, message) {
3259
4801
  return details;
3260
4802
  }
3261
4803
  function createResultError(response, result, normalized) {
3262
- const rawRecord = isRecord6(response.raw) ? response.raw : null;
4804
+ const rawRecord = isRecord8(response.raw) ? response.raw : null;
3263
4805
  const payload = resolveStructuredErrorPayload2(response.raw);
3264
4806
  const message = firstNonEmptyString2(
3265
4807
  response.error,
@@ -3454,7 +4996,14 @@ function toSingleResult(response) {
3454
4996
  function mergeOptions(...options) {
3455
4997
  return options.reduce((acc, next) => {
3456
4998
  if (!next) return acc;
3457
- return { ...acc, ...next };
4999
+ const merged = { ...acc ?? {}, ...next };
5000
+ if (acc?.headers || next.headers) {
5001
+ merged.headers = {
5002
+ ...acc?.headers ?? {},
5003
+ ...next.headers ?? {}
5004
+ };
5005
+ }
5006
+ return merged;
3458
5007
  }, void 0);
3459
5008
  }
3460
5009
  function asAthenaJsonObject(value) {
@@ -4246,42 +5795,48 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
4246
5795
  buildTypedSelectQuery
4247
5796
  });
4248
5797
  if (plan.kind === "query") {
4249
- return executeWithQueryTrace(
5798
+ return executeExperimentalRead(
5799
+ experimental,
5800
+ () => executeWithQueryTrace(
5801
+ tracer,
5802
+ {
5803
+ operation: "select",
5804
+ endpoint: "/gateway/query",
5805
+ table: resolvedTableName,
5806
+ sql: plan.query,
5807
+ payload: plan.payload,
5808
+ options
5809
+ },
5810
+ async () => {
5811
+ const queryResponse = await client.queryGateway(plan.payload, options);
5812
+ return formatGatewayResult(queryResponse, { table: resolvedTableName, operation: "select" });
5813
+ },
5814
+ callsite
5815
+ )
5816
+ );
5817
+ }
5818
+ const sql = buildDebugSelectQuery({
5819
+ tableName: resolvedTableName,
5820
+ ...plan.debug
5821
+ });
5822
+ return executeExperimentalRead(
5823
+ experimental,
5824
+ () => executeWithQueryTrace(
4250
5825
  tracer,
4251
5826
  {
4252
5827
  operation: "select",
4253
- endpoint: "/gateway/query",
5828
+ endpoint: "/gateway/fetch",
4254
5829
  table: resolvedTableName,
4255
- sql: plan.query,
5830
+ sql,
4256
5831
  payload: plan.payload,
4257
5832
  options
4258
5833
  },
4259
5834
  async () => {
4260
- const queryResponse = await client.queryGateway(plan.payload, options);
4261
- return formatGatewayResult(queryResponse, { table: resolvedTableName, operation: "select" });
5835
+ const response = await client.fetchGateway(plan.payload, options);
5836
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
4262
5837
  },
4263
5838
  callsite
4264
- );
4265
- }
4266
- const sql = buildDebugSelectQuery({
4267
- tableName: resolvedTableName,
4268
- ...plan.debug
4269
- });
4270
- return executeWithQueryTrace(
4271
- tracer,
4272
- {
4273
- operation: "select",
4274
- endpoint: "/gateway/fetch",
4275
- table: resolvedTableName,
4276
- sql,
4277
- payload: plan.payload,
4278
- options
4279
- },
4280
- async () => {
4281
- const response = await client.fetchGateway(plan.payload, options);
4282
- return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
4283
- },
4284
- callsite
5839
+ )
4285
5840
  );
4286
5841
  };
4287
5842
  const createSelectChain = (columns, options, initialCallsite) => {
@@ -4351,14 +5906,14 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
4351
5906
  if (options.limit !== void 0) {
4352
5907
  executionState.limit = options.limit;
4353
5908
  }
4354
- if (experimental?.findManyAst && canUseFindManyAstTransport(baseState) && !selectShapeUsesRelationSchema(options.select)) {
5909
+ if (experimental?.findManyAst && canUseFindManyAstTransport(baseState) && !selectShapeUsesRelationSchema(options.select) && !findManyAstWhereRequiresLegacyTransport(options.where)) {
4355
5910
  const resolvedTableName = resolveTableNameForCall(tableName, void 0);
4356
5911
  const payload = {
4357
5912
  table_name: resolvedTableName,
4358
5913
  select: options.select
4359
5914
  };
4360
5915
  if (options.where !== void 0) {
4361
- payload.where = options.where;
5916
+ payload.where = normalizeFindManyAstWhere(options.where);
4362
5917
  }
4363
5918
  const astOrder = toFindManyAstOrder(executionState.order);
4364
5919
  if (astOrder !== void 0) {
@@ -4374,22 +5929,25 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
4374
5929
  limit: executionState.limit,
4375
5930
  order: executionState.order
4376
5931
  });
4377
- return executeWithQueryTrace(
4378
- tracer,
4379
- {
4380
- operation: "select",
4381
- endpoint: "/gateway/fetch",
4382
- table: resolvedTableName,
4383
- sql,
4384
- payload
4385
- },
4386
- async () => {
4387
- const response = await client.fetchGateway(
5932
+ return executeExperimentalRead(
5933
+ experimental,
5934
+ () => executeWithQueryTrace(
5935
+ tracer,
5936
+ {
5937
+ operation: "select",
5938
+ endpoint: "/gateway/fetch",
5939
+ table: resolvedTableName,
5940
+ sql,
4388
5941
  payload
4389
- );
4390
- return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
4391
- },
4392
- callsite
5942
+ },
5943
+ async () => {
5944
+ const response = await client.fetchGateway(
5945
+ payload
5946
+ );
5947
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
5948
+ },
5949
+ callsite
5950
+ )
4393
5951
  );
4394
5952
  }
4395
5953
  return runSelect(
@@ -4637,7 +6195,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
4637
6195
  });
4638
6196
  return builder;
4639
6197
  }
4640
- function createQueryBuilder(client, formatGatewayResult, tracer) {
6198
+ function createQueryBuilder(client, formatGatewayResult, experimental, tracer) {
4641
6199
  return async function query(query, options) {
4642
6200
  const normalizedQuery = query.trim();
4643
6201
  if (!normalizedQuery) {
@@ -4645,30 +6203,39 @@ function createQueryBuilder(client, formatGatewayResult, tracer) {
4645
6203
  }
4646
6204
  const payload = { query: normalizedQuery };
4647
6205
  const callsite = captureTraceCallsite(tracer);
4648
- return executeWithQueryTrace(
4649
- tracer,
4650
- {
4651
- operation: "query",
4652
- endpoint: "/gateway/query",
4653
- sql: normalizedQuery,
4654
- payload,
4655
- options
4656
- },
4657
- async () => {
4658
- const response = await client.queryGateway(payload, options);
4659
- return formatGatewayResult(response, { operation: "query" });
4660
- },
4661
- callsite
6206
+ return executeExperimentalRead(
6207
+ experimental,
6208
+ () => executeWithQueryTrace(
6209
+ tracer,
6210
+ {
6211
+ operation: "query",
6212
+ endpoint: "/gateway/query",
6213
+ sql: normalizedQuery,
6214
+ payload,
6215
+ options
6216
+ },
6217
+ async () => {
6218
+ const response = await client.queryGateway(payload, options);
6219
+ return formatGatewayResult(response, { operation: "query" });
6220
+ },
6221
+ callsite
6222
+ )
4662
6223
  );
4663
6224
  };
4664
6225
  }
4665
6226
  function createClientFromConfig(config) {
6227
+ const gatewayHeaders = {
6228
+ ...config.headers ?? {}
6229
+ };
6230
+ if (config.auth?.bearerToken && gatewayHeaders["X-Athena-Auth-Bearer-Token"] === void 0 && gatewayHeaders["x-athena-auth-bearer-token"] === void 0) {
6231
+ gatewayHeaders["X-Athena-Auth-Bearer-Token"] = config.auth.bearerToken;
6232
+ }
4666
6233
  const gateway = createAthenaGatewayClient({
4667
6234
  baseUrl: config.baseUrl,
4668
6235
  apiKey: config.apiKey,
4669
6236
  client: config.client,
4670
6237
  backend: config.backend,
4671
- headers: config.headers
6238
+ headers: gatewayHeaders
4672
6239
  });
4673
6240
  const formatGatewayResult = createResultFormatter(config.experimental);
4674
6241
  const queryTracer = createQueryTracer(config.experimental);
@@ -4695,9 +6262,9 @@ function createClientFromConfig(config) {
4695
6262
  captureTraceCallsite(queryTracer)
4696
6263
  );
4697
6264
  };
4698
- const query = createQueryBuilder(gateway, formatGatewayResult, queryTracer);
6265
+ const query = createQueryBuilder(gateway, formatGatewayResult, config.experimental, queryTracer);
4699
6266
  const db = createDbModule({ from, rpc, query });
4700
- return {
6267
+ const sdkClient = {
4701
6268
  from,
4702
6269
  db,
4703
6270
  rpc,
@@ -4705,6 +6272,14 @@ function createClientFromConfig(config) {
4705
6272
  verifyConnection: gateway.verifyConnection,
4706
6273
  auth: auth.auth
4707
6274
  };
6275
+ if (config.experimental?.athenaStorageBackend) {
6276
+ const storageClient = {
6277
+ ...sdkClient,
6278
+ storage: createStorageModule(gateway, config.experimental.storage)
6279
+ };
6280
+ return storageClient;
6281
+ }
6282
+ return sdkClient;
4708
6283
  }
4709
6284
  var DEFAULT_BACKEND = { type: "athena" };
4710
6285
  function toBackendConfig(b) {
@@ -4735,6 +6310,12 @@ function mergeExperimentalOptions(current, next) {
4735
6310
  ...next.traceQueries
4736
6311
  };
4737
6312
  }
6313
+ if (current?.storage || next.storage) {
6314
+ merged.storage = {
6315
+ ...current?.storage ?? {},
6316
+ ...next.storage ?? {}
6317
+ };
6318
+ }
4738
6319
  return merged;
4739
6320
  }
4740
6321
  var AthenaClientBuilderImpl = class {
@@ -4745,7 +6326,6 @@ var AthenaClientBuilderImpl = class {
4745
6326
  defaultHeaders;
4746
6327
  authConfig;
4747
6328
  experimentalOptions;
4748
- isHealthTrackingEnabled = false;
4749
6329
  url(url) {
4750
6330
  this.baseUrl = url;
4751
6331
  return this;
@@ -4772,7 +6352,7 @@ var AthenaClientBuilderImpl = class {
4772
6352
  }
4773
6353
  experimental(options) {
4774
6354
  this.experimentalOptions = mergeExperimentalOptions(this.experimentalOptions, options);
4775
- return this;
6355
+ return options.athenaStorageBackend ? this : this;
4776
6356
  }
4777
6357
  options(options) {
4778
6358
  if (options.client !== void 0) {
@@ -4793,11 +6373,7 @@ var AthenaClientBuilderImpl = class {
4793
6373
  if (options.experimental !== void 0) {
4794
6374
  this.experimentalOptions = mergeExperimentalOptions(this.experimentalOptions, options.experimental);
4795
6375
  }
4796
- return this;
4797
- }
4798
- healthTracking(enabled) {
4799
- this.isHealthTrackingEnabled = enabled;
4800
- return this;
6376
+ return options.experimental?.athenaStorageBackend ? this : this;
4801
6377
  }
4802
6378
  build() {
4803
6379
  if (!this.baseUrl || !this.apiKey) {
@@ -4809,7 +6385,6 @@ var AthenaClientBuilderImpl = class {
4809
6385
  client: this.clientName,
4810
6386
  backend: this.backendConfig,
4811
6387
  headers: this.defaultHeaders,
4812
- healthTracking: this.isHealthTrackingEnabled,
4813
6388
  auth: this.authConfig,
4814
6389
  experimental: this.experimentalOptions
4815
6390
  });
@@ -4994,7 +6569,7 @@ function resolveNullishValue(mode) {
4994
6569
  if (mode === "null") return null;
4995
6570
  return "";
4996
6571
  }
4997
- function isRecord7(value) {
6572
+ function isRecord9(value) {
4998
6573
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
4999
6574
  }
5000
6575
  function isNullableColumn(model, key) {
@@ -5003,7 +6578,7 @@ function isNullableColumn(model, key) {
5003
6578
  }
5004
6579
  function toModelFormDefaults(model, values, options) {
5005
6580
  const source = values;
5006
- if (!isRecord7(source)) {
6581
+ if (!isRecord9(source)) {
5007
6582
  return {};
5008
6583
  }
5009
6584
  const mode = options?.nullishMode ?? "empty-string";
@@ -5078,6 +6653,90 @@ function resolveProviderSchemas(providerConfig) {
5078
6653
  return [...DEFAULT_POSTGRES_SCHEMAS];
5079
6654
  }
5080
6655
 
6656
+ // src/generator/env.ts
6657
+ function readEnvStringValue(key) {
6658
+ if (typeof process === "undefined" || !process.env) {
6659
+ return void 0;
6660
+ }
6661
+ const value = process.env[key];
6662
+ if (typeof value !== "string") {
6663
+ return void 0;
6664
+ }
6665
+ const trimmed = value.trim();
6666
+ return trimmed.length > 0 ? trimmed : void 0;
6667
+ }
6668
+ function throwMissingEnvVar(key) {
6669
+ throw new Error(
6670
+ `Generator config env var ${key} is missing or empty. Set ${key} or provide a default value.`
6671
+ );
6672
+ }
6673
+ function resolveEnvValue(key, options, resolver) {
6674
+ const rawValue = readEnvStringValue(key);
6675
+ if (rawValue === void 0) {
6676
+ if (options?.default !== void 0) {
6677
+ return options.default;
6678
+ }
6679
+ if (options?.optional) {
6680
+ return void 0;
6681
+ }
6682
+ return throwMissingEnvVar(key);
6683
+ }
6684
+ return resolver(rawValue);
6685
+ }
6686
+ function resolveStringEnv(key, options) {
6687
+ return resolveEnvValue(key, options, (value) => value);
6688
+ }
6689
+ function resolveBooleanEnv(key, options) {
6690
+ return resolveEnvValue(key, options, (value) => parseBooleanFlag2(value, false));
6691
+ }
6692
+ function resolveListEnv(key, options) {
6693
+ return resolveEnvValue(key, options, (value) => {
6694
+ const separator = options?.separator ?? ",";
6695
+ return value.split(separator).map((entry) => entry.trim()).filter((entry, index, entries) => entry.length > 0 && entries.indexOf(entry) === index);
6696
+ })?.slice();
6697
+ }
6698
+ function resolveJsonEnv(key, options) {
6699
+ return resolveEnvValue(key, options, (value) => {
6700
+ try {
6701
+ return JSON.parse(value);
6702
+ } catch (error) {
6703
+ const message = error instanceof Error ? error.message : String(error);
6704
+ throw new Error(`Generator config env var ${key} must contain valid JSON. ${message}`);
6705
+ }
6706
+ });
6707
+ }
6708
+ function resolveOneOfEnv(key, allowedValues, options) {
6709
+ return resolveEnvValue(key, options, (value) => {
6710
+ if (allowedValues.includes(value)) {
6711
+ return value;
6712
+ }
6713
+ throw new Error(
6714
+ `Generator config env var ${key} must be one of: ${allowedValues.join(", ")}. Received: ${value}.`
6715
+ );
6716
+ });
6717
+ }
6718
+ function generatorEnvString(key, options) {
6719
+ return resolveStringEnv(key, options);
6720
+ }
6721
+ function generatorEnvBoolean(key, options) {
6722
+ return resolveBooleanEnv(key, options);
6723
+ }
6724
+ function generatorEnvList(key, options) {
6725
+ return resolveListEnv(key, options);
6726
+ }
6727
+ function generatorEnvJson(key, options) {
6728
+ return resolveJsonEnv(key, options);
6729
+ }
6730
+ function generatorEnvOneOf(key, allowedValues, options) {
6731
+ return resolveOneOfEnv(key, allowedValues, options);
6732
+ }
6733
+ var generatorEnv = Object.assign(generatorEnvString, {
6734
+ boolean: generatorEnvBoolean,
6735
+ list: generatorEnvList,
6736
+ json: generatorEnvJson,
6737
+ oneOf: generatorEnvOneOf
6738
+ });
6739
+
5081
6740
  // src/generator/postgres-type-mapping.ts
5082
6741
  var NUMBER_TYPES = /* @__PURE__ */ new Set([
5083
6742
  "int2",
@@ -5194,6 +6853,433 @@ function resolvePostgresColumnType(column) {
5194
6853
  return wrapArrayType(baseType, column.arrayDimensions);
5195
6854
  }
5196
6855
 
6856
+ // src/auth/server.ts
6857
+ var DEFAULT_AUTH_BASE_PATH = "/api/auth";
6858
+ var ATHENA_AUTH_BASE_ERROR_CODES = {
6859
+ HANDLER_NOT_CONFIGURED: "HANDLER_NOT_CONFIGURED",
6860
+ INVALID_BASE_URL: "INVALID_BASE_URL",
6861
+ UNTRUSTED_HOST: "UNTRUSTED_HOST"
6862
+ };
6863
+ function capitalize(value) {
6864
+ return value.length > 0 ? `${value[0]?.toUpperCase()}${value.slice(1)}` : value;
6865
+ }
6866
+ function serializeSetCookieValue(name, value, attributes) {
6867
+ const parts = [`${name}=${encodeURIComponent(value)}`];
6868
+ const knownKeys = /* @__PURE__ */ new Set([
6869
+ "maxAge",
6870
+ "expires",
6871
+ "domain",
6872
+ "path",
6873
+ "secure",
6874
+ "httpOnly",
6875
+ "partitioned",
6876
+ "sameSite"
6877
+ ]);
6878
+ if (attributes.maxAge !== void 0) {
6879
+ parts.push(`Max-Age=${Math.trunc(attributes.maxAge)}`);
6880
+ }
6881
+ if (attributes.expires instanceof Date) {
6882
+ parts.push(`Expires=${attributes.expires.toUTCString()}`);
6883
+ }
6884
+ if (attributes.domain) {
6885
+ parts.push(`Domain=${attributes.domain}`);
6886
+ }
6887
+ if (attributes.path) {
6888
+ parts.push(`Path=${attributes.path}`);
6889
+ }
6890
+ if (attributes.secure) {
6891
+ parts.push("Secure");
6892
+ }
6893
+ if (attributes.httpOnly) {
6894
+ parts.push("HttpOnly");
6895
+ }
6896
+ if (attributes.partitioned) {
6897
+ parts.push("Partitioned");
6898
+ }
6899
+ if (attributes.sameSite) {
6900
+ parts.push(`SameSite=${capitalize(attributes.sameSite)}`);
6901
+ }
6902
+ for (const [key, rawValue] of Object.entries(attributes)) {
6903
+ if (knownKeys.has(key) || rawValue === void 0 || rawValue === null || rawValue === false) {
6904
+ continue;
6905
+ }
6906
+ if (rawValue === true) {
6907
+ parts.push(key);
6908
+ continue;
6909
+ }
6910
+ parts.push(`${key}=${String(rawValue)}`);
6911
+ }
6912
+ return parts.join("; ");
6913
+ }
6914
+ function readCookieFromHeaders(headers, name) {
6915
+ const cookieHeader = headers?.get("cookie");
6916
+ if (!cookieHeader) {
6917
+ return void 0;
6918
+ }
6919
+ return parseCookies(cookieHeader).get(name);
6920
+ }
6921
+ function isRecord10(value) {
6922
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
6923
+ }
6924
+ function resolveSessionCandidate(value) {
6925
+ if (!isRecord10(value)) {
6926
+ return null;
6927
+ }
6928
+ const session = isRecord10(value.session) ? value.session : void 0;
6929
+ const user = isRecord10(value.user) ? value.user : void 0;
6930
+ if (session && typeof session.token === "string" && session.token.length > 0 && user) {
6931
+ return {
6932
+ session,
6933
+ user
6934
+ };
6935
+ }
6936
+ return null;
6937
+ }
6938
+ function inferSessionPair(returned) {
6939
+ return resolveSessionCandidate(returned) ?? (isRecord10(returned) ? resolveSessionCandidate(returned.data) : null) ?? (isRecord10(returned) ? resolveSessionCandidate(returned.session) : null);
6940
+ }
6941
+ function resolveResponseHeaders(ctx) {
6942
+ if (ctx.context.responseHeaders instanceof Headers) {
6943
+ return ctx.context.responseHeaders;
6944
+ }
6945
+ const headers = new Headers();
6946
+ ctx.context.responseHeaders = headers;
6947
+ return headers;
6948
+ }
6949
+ function normalizeBaseURL(baseURL) {
6950
+ return baseURL.replace(/\/$/, "");
6951
+ }
6952
+ function normalizeBasePath(basePath) {
6953
+ if (!basePath || basePath === "/") {
6954
+ return DEFAULT_AUTH_BASE_PATH;
6955
+ }
6956
+ const normalized = basePath.startsWith("/") ? basePath : `/${basePath}`;
6957
+ return normalized.endsWith("/") && normalized.length > 1 ? normalized.slice(0, -1) : normalized;
6958
+ }
6959
+ function isDynamicBaseURLConfig2(baseURL) {
6960
+ return typeof baseURL === "object" && baseURL !== null && "allowedHosts" in baseURL && Array.isArray(baseURL.allowedHosts);
6961
+ }
6962
+ function getRequestUrl(request) {
6963
+ try {
6964
+ return new URL(request.url);
6965
+ } catch {
6966
+ return new URL("http://localhost");
6967
+ }
6968
+ }
6969
+ function getRequestHost(request, url) {
6970
+ const forwardedHost = request.headers.get("x-forwarded-host")?.split(",")[0]?.trim();
6971
+ const host = forwardedHost || request.headers.get("host") || url.host;
6972
+ return host || null;
6973
+ }
6974
+ function getRequestProtocol(request, configuredProtocol, url) {
6975
+ if (configuredProtocol === "http" || configuredProtocol === "https") {
6976
+ return configuredProtocol;
6977
+ }
6978
+ const forwardedProto = request.headers.get("x-forwarded-proto")?.split(",")[0]?.trim();
6979
+ if (forwardedProto === "http" || forwardedProto === "https") {
6980
+ return forwardedProto;
6981
+ }
6982
+ if (url.protocol === "http:" || url.protocol === "https:") {
6983
+ return url.protocol.slice(0, -1);
6984
+ }
6985
+ return "http";
6986
+ }
6987
+ function resolveRequestBaseURL(baseURL, request) {
6988
+ if (typeof baseURL === "string") {
6989
+ return normalizeBaseURL(baseURL);
6990
+ }
6991
+ const requestUrl = getRequestUrl(request);
6992
+ const host = getRequestHost(request, requestUrl);
6993
+ if (!host) {
6994
+ return null;
6995
+ }
6996
+ if (isDynamicBaseURLConfig2(baseURL)) {
6997
+ const allowedHosts = baseURL.allowedHosts ?? [];
6998
+ if (allowedHosts.length > 0 && !allowedHosts.includes(host)) {
6999
+ return null;
7000
+ }
7001
+ }
7002
+ const protocol = typeof baseURL === "object" && baseURL !== null ? getRequestProtocol(request, baseURL.protocol, requestUrl) : getRequestProtocol(request, void 0, requestUrl);
7003
+ return `${protocol}://${host}`;
7004
+ }
7005
+ function getOrigin(baseURL) {
7006
+ if (!baseURL) {
7007
+ return void 0;
7008
+ }
7009
+ try {
7010
+ return new URL(baseURL).origin;
7011
+ } catch {
7012
+ return void 0;
7013
+ }
7014
+ }
7015
+ async function resolveTrustedOrigins(config, baseURL, request) {
7016
+ const resolved = typeof config.trustedOrigins === "function" ? await config.trustedOrigins(request) : config.trustedOrigins ?? [];
7017
+ const values = [
7018
+ getOrigin(baseURL),
7019
+ ...resolved
7020
+ ];
7021
+ return Array.from(new Set(values.filter((value) => typeof value === "string" && value.length > 0)));
7022
+ }
7023
+ async function resolveTrustedProviders(config, request) {
7024
+ const configured = typeof config.trustedProviders === "function" ? await config.trustedProviders(request) : config.trustedProviders ?? [];
7025
+ const values = [
7026
+ ...Object.keys(config.socialProviders ?? {}),
7027
+ ...configured
7028
+ ];
7029
+ return Array.from(new Set(values.filter((value) => typeof value === "string" && value.length > 0)));
7030
+ }
7031
+ function createJsonResponse(payload, init) {
7032
+ const headers = new Headers(init?.headers);
7033
+ if (!headers.has("content-type")) {
7034
+ headers.set("content-type", "application/json; charset=utf-8");
7035
+ }
7036
+ return new Response(JSON.stringify(payload), {
7037
+ ...init,
7038
+ headers
7039
+ });
7040
+ }
7041
+ function mergeResponseHeaders(response, headers) {
7042
+ return new Response(response.body, {
7043
+ status: response.status,
7044
+ statusText: response.statusText,
7045
+ headers
7046
+ });
7047
+ }
7048
+ function defineAthenaAuthConfig(config) {
7049
+ return config;
7050
+ }
7051
+ function athenaAuth(config) {
7052
+ const normalizedBasePath = normalizeBasePath(config.basePath);
7053
+ const staticBaseURL = typeof config.baseURL === "string" ? normalizeBaseURL(config.baseURL) : void 0;
7054
+ const runtime = {
7055
+ baseURL: staticBaseURL,
7056
+ basePath: normalizedBasePath,
7057
+ secret: config.secret,
7058
+ cookies: {
7059
+ session: config.session,
7060
+ advanced: config.advanced
7061
+ }
7062
+ };
7063
+ const resolvedDatabase = typeof config.database === "function" ? config.database(runtime) : config.database;
7064
+ const cookies = getCookies({
7065
+ baseURL: staticBaseURL ?? config.baseURL,
7066
+ session: config.session,
7067
+ advanced: config.advanced
7068
+ });
7069
+ const auth = {};
7070
+ const createCookieContext = (input = {}) => {
7071
+ const responseHeaders = input.responseHeaders ?? new Headers();
7072
+ const runtimeHeaders = input.headers;
7073
+ const authCookies = input.cookies ?? auth.cookies;
7074
+ const setCookie = input.setCookie ?? ((name, value, attributes) => {
7075
+ responseHeaders.append(
7076
+ "set-cookie",
7077
+ serializeSetCookieValue(name, value, attributes)
7078
+ );
7079
+ });
7080
+ return {
7081
+ headers: runtimeHeaders,
7082
+ getCookie: input.getCookie ?? ((name) => readCookieFromHeaders(runtimeHeaders, name)),
7083
+ setCookie,
7084
+ logger: input.logger,
7085
+ setSignedCookie: input.setSignedCookie,
7086
+ getSignedCookie: input.getSignedCookie,
7087
+ context: {
7088
+ secret: runtime.secret,
7089
+ authCookies,
7090
+ sessionConfig: {
7091
+ expiresIn: config.session?.expiresIn
7092
+ },
7093
+ options: {
7094
+ session: {
7095
+ cookieCache: config.session?.cookieCache
7096
+ },
7097
+ account: {
7098
+ storeAccountCookie: true
7099
+ }
7100
+ },
7101
+ setNewSession: input.setNewSession
7102
+ }
7103
+ };
7104
+ };
7105
+ const setSession = async (input, session, dontRememberMe, overrides) => {
7106
+ const cookieContext = createCookieContext(input);
7107
+ await setSessionCookie(cookieContext, session, dontRememberMe, overrides);
7108
+ };
7109
+ const clearSession = (input, skipDontRememberMe) => {
7110
+ const cookieContext = createCookieContext(input);
7111
+ deleteSessionCookie(cookieContext, skipDontRememberMe);
7112
+ };
7113
+ const applyResponseCookies = async (ctx) => {
7114
+ const responseHeaders = resolveResponseHeaders(ctx);
7115
+ const session = ctx.context.setSession ?? inferSessionPair(ctx.context.returned);
7116
+ if (ctx.context.clearSession) {
7117
+ clearSession({
7118
+ headers: ctx.headers,
7119
+ responseHeaders
7120
+ });
7121
+ }
7122
+ if (session) {
7123
+ await setSession(
7124
+ {
7125
+ headers: ctx.headers,
7126
+ responseHeaders
7127
+ },
7128
+ session,
7129
+ ctx.context.dontRememberMe,
7130
+ ctx.context.cookieOverrides
7131
+ );
7132
+ }
7133
+ return responseHeaders;
7134
+ };
7135
+ const runAfterHooks = async (ctx) => {
7136
+ for (const plugin of auth.plugins) {
7137
+ for (const hook of plugin.hooks?.after ?? []) {
7138
+ if (!hook.matcher(ctx)) {
7139
+ continue;
7140
+ }
7141
+ await hook.handler({
7142
+ ...ctx,
7143
+ auth
7144
+ });
7145
+ }
7146
+ }
7147
+ return ctx;
7148
+ };
7149
+ const resolveRequestContext = async (request) => {
7150
+ const requestUrl = getRequestUrl(request);
7151
+ const resolvedBaseURL = resolveRequestBaseURL(config.baseURL, request);
7152
+ if (!resolvedBaseURL) {
7153
+ throw new Error(
7154
+ isDynamicBaseURLConfig2(config.baseURL) ? "Could not resolve base URL from request. Check allowedHosts/baseURL." : "Could not resolve base URL from request."
7155
+ );
7156
+ }
7157
+ const requestCookies = getCookies({
7158
+ baseURL: resolvedBaseURL,
7159
+ session: config.session,
7160
+ advanced: config.advanced
7161
+ });
7162
+ const trustedOrigins = await resolveTrustedOrigins(config, resolvedBaseURL, request);
7163
+ const trustedProviders = await resolveTrustedProviders(config, request);
7164
+ return {
7165
+ auth,
7166
+ request,
7167
+ url: requestUrl,
7168
+ path: requestUrl.pathname,
7169
+ basePath: normalizedBasePath,
7170
+ baseURL: resolvedBaseURL,
7171
+ origin: getOrigin(resolvedBaseURL) ?? resolvedBaseURL,
7172
+ headers: request.headers,
7173
+ cookies: requestCookies,
7174
+ trustedOrigins,
7175
+ trustedProviders,
7176
+ options: config,
7177
+ runtime: {
7178
+ ...runtime,
7179
+ baseURL: resolvedBaseURL
7180
+ },
7181
+ database: auth.database,
7182
+ socialProviders: auth.socialProviders
7183
+ };
7184
+ };
7185
+ const handler = async (request) => {
7186
+ const requestContext = await resolveRequestContext(request);
7187
+ if (typeof config.handler !== "function") {
7188
+ return createJsonResponse(
7189
+ {
7190
+ ok: false,
7191
+ code: ATHENA_AUTH_BASE_ERROR_CODES.HANDLER_NOT_CONFIGURED,
7192
+ error: "No native auth handler was configured for this Athena auth instance.",
7193
+ path: requestContext.path,
7194
+ basePath: requestContext.basePath
7195
+ },
7196
+ { status: 501 }
7197
+ );
7198
+ }
7199
+ const result = await config.handler(requestContext);
7200
+ if (result instanceof Response) {
7201
+ return result;
7202
+ }
7203
+ const response = result.response ?? (result.returned !== void 0 ? createJsonResponse(result.returned) : new Response(null, { status: 204 }));
7204
+ const responseHeaders = new Headers(response.headers);
7205
+ await runAfterHooks({
7206
+ path: requestContext.path,
7207
+ headers: request.headers,
7208
+ context: {
7209
+ responseHeaders,
7210
+ returned: result.returned,
7211
+ setSession: result.setSession,
7212
+ clearSession: result.clearSession,
7213
+ dontRememberMe: result.dontRememberMe,
7214
+ cookieOverrides: result.cookieOverrides
7215
+ }
7216
+ });
7217
+ return mergeResponseHeaders(response, responseHeaders);
7218
+ };
7219
+ const api = Object.assign(
7220
+ {
7221
+ applyResponseCookies,
7222
+ clearSession,
7223
+ createCookieContext,
7224
+ getCookieCache,
7225
+ getSessionCookie,
7226
+ resolveRequestContext,
7227
+ runAfterHooks,
7228
+ setSession
7229
+ },
7230
+ config.api ?? {}
7231
+ );
7232
+ const $ERROR_CODES = {
7233
+ ...auth.plugins?.reduce((acc, plugin) => {
7234
+ if (plugin.$ERROR_CODES) {
7235
+ return {
7236
+ ...acc,
7237
+ ...plugin.$ERROR_CODES
7238
+ };
7239
+ }
7240
+ return acc;
7241
+ }, {}),
7242
+ ...config.errorCodes ?? {},
7243
+ ...ATHENA_AUTH_BASE_ERROR_CODES
7244
+ };
7245
+ Object.assign(auth, {
7246
+ config,
7247
+ options: config,
7248
+ runtime,
7249
+ database: resolvedDatabase,
7250
+ socialProviders: config.socialProviders ?? {},
7251
+ plugins: [...config.plugins ?? []],
7252
+ cookies,
7253
+ api,
7254
+ $ERROR_CODES,
7255
+ createCookieContext,
7256
+ setSession,
7257
+ clearSession,
7258
+ applyResponseCookies,
7259
+ runAfterHooks,
7260
+ resolveRequestContext,
7261
+ handler
7262
+ });
7263
+ auth.$context = Promise.all([
7264
+ resolveTrustedOrigins(config, staticBaseURL),
7265
+ resolveTrustedProviders(config)
7266
+ ]).then(([trustedOrigins, trustedProviders]) => ({
7267
+ auth,
7268
+ options: config,
7269
+ runtime,
7270
+ basePath: normalizedBasePath,
7271
+ baseURL: staticBaseURL,
7272
+ origin: getOrigin(staticBaseURL),
7273
+ database: auth.database,
7274
+ socialProviders: auth.socialProviders,
7275
+ plugins: auth.plugins,
7276
+ cookies: auth.cookies,
7277
+ trustedOrigins,
7278
+ trustedProviders
7279
+ }));
7280
+ return auth;
7281
+ }
7282
+
5197
7283
  // src/browser.ts
5198
7284
  function throwBrowserUnsupported(apiName) {
5199
7285
  throw new Error(
@@ -5225,22 +7311,28 @@ async function runSchemaGenerator(options = {}) {
5225
7311
  return throwBrowserUnsupported("runSchemaGenerator");
5226
7312
  }
5227
7313
 
7314
+ exports.ATHENA_AUTH_BASE_ERROR_CODES = ATHENA_AUTH_BASE_ERROR_CODES;
5228
7315
  exports.AthenaClient = AthenaClient;
5229
7316
  exports.AthenaError = AthenaError;
5230
7317
  exports.AthenaErrorCategory = AthenaErrorCategory;
5231
7318
  exports.AthenaErrorCode = AthenaErrorCode;
5232
7319
  exports.AthenaErrorKind = AthenaErrorKind;
5233
7320
  exports.AthenaGatewayError = AthenaGatewayError;
7321
+ exports.AthenaStorageError = AthenaStorageError;
7322
+ exports.AthenaStorageErrorCode = AthenaStorageErrorCode;
5234
7323
  exports.Backend = Backend;
5235
7324
  exports.DEFAULT_POSTGRES_SCHEMAS = DEFAULT_POSTGRES_SCHEMAS;
5236
7325
  exports.assertInt = assertInt;
7326
+ exports.athenaAuth = athenaAuth;
5237
7327
  exports.coerceInt = coerceInt;
7328
+ exports.createAthenaStorageError = createAthenaStorageError;
5238
7329
  exports.createAuthClient = createAuthClient;
5239
7330
  exports.createAuthReactEmailInput = createAuthReactEmailInput;
5240
7331
  exports.createClient = createClient;
5241
7332
  exports.createModelFormAdapter = createModelFormAdapter;
5242
7333
  exports.createPostgresIntrospectionProvider = createPostgresIntrospectionProvider;
5243
7334
  exports.createTypedClient = createTypedClient;
7335
+ exports.defineAthenaAuthConfig = defineAthenaAuthConfig;
5244
7336
  exports.defineAuthEmailTemplate = defineAuthEmailTemplate;
5245
7337
  exports.defineDatabase = defineDatabase;
5246
7338
  exports.defineGeneratorConfig = defineGeneratorConfig;
@@ -5249,6 +7341,7 @@ exports.defineRegistry = defineRegistry;
5249
7341
  exports.defineSchema = defineSchema;
5250
7342
  exports.findGeneratorConfigPath = findGeneratorConfigPath;
5251
7343
  exports.generateArtifactsFromSnapshot = generateArtifactsFromSnapshot;
7344
+ exports.generatorEnv = generatorEnv;
5252
7345
  exports.identifier = identifier;
5253
7346
  exports.isAthenaGatewayError = isAthenaGatewayError;
5254
7347
  exports.isOk = isOk;
@@ -5265,6 +7358,7 @@ exports.resolveGeneratorProvider = resolveGeneratorProvider;
5265
7358
  exports.resolvePostgresColumnType = resolvePostgresColumnType;
5266
7359
  exports.resolveProviderSchemas = resolveProviderSchemas;
5267
7360
  exports.runSchemaGenerator = runSchemaGenerator;
7361
+ exports.storageSdkManifest = storageSdkManifest;
5268
7362
  exports.toModelFormDefaults = toModelFormDefaults;
5269
7363
  exports.toModelPayload = toModelPayload;
5270
7364
  exports.unwrap = unwrap;