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