@xylex-group/athena 2.4.1 → 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 (41) hide show
  1. package/README.md +52 -1
  2. package/bin/athena-js.js +0 -0
  3. package/dist/browser.cjs +1912 -49
  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 +1905 -50
  8. package/dist/browser.js.map +1 -1
  9. package/dist/cli/index.cjs +708 -22
  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 +708 -22
  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 +1912 -49
  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 +1905 -50
  24. package/dist/index.js.map +1 -1
  25. package/dist/{model-form-4LPnOPAF.d.cts → model-form-BaHWi3gm.d.cts} +1 -1
  26. package/dist/{model-form-CO4-LmNC.d.ts → model-form-Dh6gWjL0.d.ts} +1 -1
  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-Buhcpglm.d.ts → react-email-B8O1Jeff.d.cts} +596 -23
  30. package/dist/{react-email-6mOyxBo4.d.cts → react-email-CDEF0jij.d.ts} +596 -23
  31. package/dist/react.cjs +1 -1
  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 +1 -1
  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/package.json +193 -192
package/dist/browser.cjs CHANGED
@@ -127,6 +127,60 @@ function buildAthenaGatewayUrl(baseUrl, path) {
127
127
  return `${baseUrl}${path}`;
128
128
  }
129
129
 
130
+ // src/cookies/base64.ts
131
+ function getAtob() {
132
+ const candidate = globalThis.atob;
133
+ return typeof candidate === "function" ? candidate : void 0;
134
+ }
135
+ function getBtoa() {
136
+ const candidate = globalThis.btoa;
137
+ return typeof candidate === "function" ? candidate : void 0;
138
+ }
139
+ function bytesToBinaryString(bytes) {
140
+ let result = "";
141
+ for (const byte of bytes) {
142
+ result += String.fromCharCode(byte);
143
+ }
144
+ return result;
145
+ }
146
+ function binaryStringToBytes(binary) {
147
+ const bytes = new Uint8Array(binary.length);
148
+ for (let i = 0; i < binary.length; i++) {
149
+ bytes[i] = binary.charCodeAt(i);
150
+ }
151
+ return bytes;
152
+ }
153
+ function encodeBase64(bytes) {
154
+ const btoaFn = getBtoa();
155
+ if (btoaFn) {
156
+ return btoaFn(bytesToBinaryString(bytes));
157
+ }
158
+ return Buffer.from(bytes).toString("base64");
159
+ }
160
+ function decodeBase64(base64) {
161
+ const atobFn = getAtob();
162
+ if (atobFn) {
163
+ return binaryStringToBytes(atobFn(base64));
164
+ }
165
+ return new Uint8Array(Buffer.from(base64, "base64"));
166
+ }
167
+ function encodeBytesToBase64Url(bytes) {
168
+ return encodeBase64(bytes).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
169
+ }
170
+ function encodeStringToBase64Url(value) {
171
+ const bytes = new TextEncoder().encode(value);
172
+ return encodeBytesToBase64Url(bytes);
173
+ }
174
+ function decodeBase64UrlToBytes(value) {
175
+ const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
176
+ const paddingLength = normalized.length % 4;
177
+ const padded = paddingLength === 0 ? normalized : `${normalized}${"=".repeat(4 - paddingLength)}`;
178
+ return decodeBase64(padded);
179
+ }
180
+ function decodeBase64UrlToString(value) {
181
+ return new TextDecoder().decode(decodeBase64UrlToBytes(value));
182
+ }
183
+
130
184
  // src/cookies/cookie-utils.ts
131
185
  var SECURE_COOKIE_PREFIX = "__Secure-";
132
186
  function parseCookies(cookieHeader) {
@@ -138,12 +192,480 @@ function parseCookies(cookieHeader) {
138
192
  });
139
193
  return cookieMap;
140
194
  }
195
+
196
+ // src/cookies/crypto.ts
197
+ var HS256_ALG = "HS256";
198
+ async function getSubtleCrypto() {
199
+ const globalCrypto = globalThis.crypto;
200
+ if (globalCrypto?.subtle) {
201
+ return globalCrypto.subtle;
202
+ }
203
+ const { webcrypto } = await import('crypto');
204
+ const subtle = webcrypto.subtle;
205
+ if (!subtle) {
206
+ throw new Error("Web Crypto subtle API is unavailable.");
207
+ }
208
+ return subtle;
209
+ }
210
+ async function importHmacKey(secret, usage) {
211
+ const subtle = await getSubtleCrypto();
212
+ return subtle.importKey(
213
+ "raw",
214
+ new TextEncoder().encode(secret),
215
+ {
216
+ name: "HMAC",
217
+ hash: "SHA-256"
218
+ },
219
+ false,
220
+ [usage]
221
+ );
222
+ }
223
+ function bufferToBytes(buffer) {
224
+ return new Uint8Array(buffer);
225
+ }
226
+ function parseJwtPayload(payloadSegment) {
227
+ try {
228
+ const decoded = decodeBase64UrlToString(payloadSegment);
229
+ const payload = JSON.parse(decoded);
230
+ if (!payload || typeof payload !== "object") {
231
+ return null;
232
+ }
233
+ return payload;
234
+ } catch {
235
+ return null;
236
+ }
237
+ }
238
+ function isJwtExpired(payload) {
239
+ const exp = payload.exp;
240
+ if (typeof exp !== "number") {
241
+ return false;
242
+ }
243
+ return exp < Math.floor(Date.now() / 1e3);
244
+ }
245
+ async function signHmacBase64Url(secret, value) {
246
+ const subtle = await getSubtleCrypto();
247
+ const key = await importHmacKey(secret, "sign");
248
+ const signature = await subtle.sign("HMAC", key, new TextEncoder().encode(value));
249
+ return encodeBytesToBase64Url(bufferToBytes(signature));
250
+ }
251
+ async function signJwtHS256(payload, secret, expiresIn = 60 * 5) {
252
+ const now = Math.floor(Date.now() / 1e3);
253
+ const header = { alg: HS256_ALG, typ: "JWT" };
254
+ const fullPayload = {
255
+ ...payload,
256
+ iat: now,
257
+ exp: now + expiresIn
258
+ };
259
+ const headerPart = encodeStringToBase64Url(JSON.stringify(header));
260
+ const payloadPart = encodeStringToBase64Url(JSON.stringify(fullPayload));
261
+ const message = `${headerPart}.${payloadPart}`;
262
+ const signature = await signHmacBase64Url(secret, message);
263
+ return `${message}.${signature}`;
264
+ }
265
+ async function verifyJwtHS256(token, secret) {
266
+ const parts = token.split(".");
267
+ if (parts.length !== 3) {
268
+ return null;
269
+ }
270
+ const [headerPart, payloadPart, signaturePart] = parts;
271
+ if (!headerPart || !payloadPart || !signaturePart) {
272
+ return null;
273
+ }
274
+ let header = null;
275
+ try {
276
+ header = JSON.parse(decodeBase64UrlToString(headerPart));
277
+ } catch {
278
+ return null;
279
+ }
280
+ if (!header || header.alg !== HS256_ALG) {
281
+ return null;
282
+ }
283
+ const payload = parseJwtPayload(payloadPart);
284
+ if (!payload) {
285
+ return null;
286
+ }
287
+ const expectedSignature = await signHmacBase64Url(secret, `${headerPart}.${payloadPart}`);
288
+ if (expectedSignature !== signaturePart) {
289
+ return null;
290
+ }
291
+ if (isJwtExpired(payload)) {
292
+ return null;
293
+ }
294
+ return payload;
295
+ }
296
+
297
+ // src/cookies/session-store.ts
298
+ var ALLOWED_COOKIE_SIZE = 4096;
299
+ var ESTIMATED_EMPTY_COOKIE_SIZE = 200;
300
+ var CHUNK_SIZE = ALLOWED_COOKIE_SIZE - ESTIMATED_EMPTY_COOKIE_SIZE;
301
+ function getChunkIndex(cookieName) {
302
+ const parts = cookieName.split(".");
303
+ const lastPart = parts[parts.length - 1];
304
+ const index = parseInt(lastPart || "0", 10);
305
+ return Number.isNaN(index) ? 0 : index;
306
+ }
307
+ function readExistingChunks(cookieName, ctx) {
308
+ const chunks = {};
309
+ const cookies = parseCookies(ctx.headers?.get("cookie") || "");
310
+ for (const [name, value] of cookies) {
311
+ if (name.startsWith(cookieName)) {
312
+ chunks[name] = value;
313
+ }
314
+ }
315
+ return chunks;
316
+ }
317
+ function joinChunks(chunks) {
318
+ const sortedKeys = Object.keys(chunks).sort((left, right) => getChunkIndex(left) - getChunkIndex(right));
319
+ return sortedKeys.map((key) => chunks[key]).join("");
320
+ }
321
+ function chunkCookie(storeName, cookie, chunks, ctx) {
322
+ const chunkCount = Math.ceil(cookie.value.length / CHUNK_SIZE);
323
+ if (chunkCount === 1) {
324
+ chunks[cookie.name] = cookie.value;
325
+ return [cookie];
326
+ }
327
+ const cookies = [];
328
+ for (let index = 0; index < chunkCount; index++) {
329
+ const name = `${cookie.name}.${index}`;
330
+ const start = index * CHUNK_SIZE;
331
+ const value = cookie.value.substring(start, start + CHUNK_SIZE);
332
+ cookies.push({
333
+ ...cookie,
334
+ name,
335
+ value
336
+ });
337
+ chunks[name] = value;
338
+ }
339
+ ctx.logger?.debug?.(`CHUNKING_${storeName.toUpperCase()}_COOKIE`, {
340
+ message: `${storeName} cookie exceeds allowed ${ALLOWED_COOKIE_SIZE} bytes.`,
341
+ emptyCookieSize: ESTIMATED_EMPTY_COOKIE_SIZE,
342
+ valueSize: cookie.value.length,
343
+ chunkCount,
344
+ chunks: cookies.map((entry) => entry.value.length + ESTIMATED_EMPTY_COOKIE_SIZE)
345
+ });
346
+ return cookies;
347
+ }
348
+ function getCleanCookies(chunks, cookieOptions) {
349
+ const cleanedChunks = {};
350
+ for (const name in chunks) {
351
+ cleanedChunks[name] = {
352
+ name,
353
+ value: "",
354
+ attributes: {
355
+ ...cookieOptions,
356
+ maxAge: 0
357
+ }
358
+ };
359
+ }
360
+ return cleanedChunks;
361
+ }
362
+ var storeFactory = (storeName) => (cookieName, cookieOptions, ctx) => {
363
+ const chunks = readExistingChunks(cookieName, ctx);
364
+ return {
365
+ getValue() {
366
+ return joinChunks(chunks);
367
+ },
368
+ hasChunks() {
369
+ return Object.keys(chunks).length > 0;
370
+ },
371
+ chunk(value, options) {
372
+ const cleanedChunks = getCleanCookies(chunks, cookieOptions);
373
+ for (const name in chunks) {
374
+ delete chunks[name];
375
+ }
376
+ const cookies = cleanedChunks;
377
+ const chunked = chunkCookie(
378
+ storeName,
379
+ {
380
+ name: cookieName,
381
+ value,
382
+ attributes: {
383
+ ...cookieOptions,
384
+ ...options
385
+ }
386
+ },
387
+ chunks,
388
+ ctx
389
+ );
390
+ for (const chunk of chunked) {
391
+ cookies[chunk.name] = chunk;
392
+ }
393
+ return Object.values(cookies);
394
+ },
395
+ clean() {
396
+ const cleanedChunks = getCleanCookies(chunks, cookieOptions);
397
+ for (const name in chunks) {
398
+ delete chunks[name];
399
+ }
400
+ return Object.values(cleanedChunks);
401
+ },
402
+ setCookies(cookies) {
403
+ for (const cookie of cookies) {
404
+ ctx.setCookie(cookie.name, cookie.value, cookie.attributes);
405
+ }
406
+ }
407
+ };
408
+ };
409
+ var createSessionStore = storeFactory("Session");
410
+ var createAccountStore = storeFactory("Account");
411
+
412
+ // src/cookies/index.ts
413
+ var DEFAULT_COOKIE_PREFIX = "athena-auth";
414
+ var LEGACY_COOKIE_PREFIX = "better-auth";
415
+ var DEFAULT_SESSION_MAX_AGE = 7 * 24 * 60 * 60;
416
+ var DEFAULT_CACHE_MAX_AGE = 60 * 5;
417
+ function isProductionRuntime() {
418
+ return typeof process !== "undefined" && process.env?.NODE_ENV === "production";
419
+ }
420
+ function getEnvironmentSecret() {
421
+ if (typeof process === "undefined") {
422
+ return void 0;
423
+ }
424
+ return process.env?.ATHENA_AUTH_SECRET || process.env?.BETTER_AUTH_SECRET || process.env?.AUTH_SECRET;
425
+ }
426
+ function isDynamicBaseURLConfig(baseURL) {
427
+ return typeof baseURL === "object" && baseURL !== null && "allowedHosts" in baseURL && Array.isArray(baseURL.allowedHosts);
428
+ }
429
+ function resolveCookiePrefixes(primaryPrefix) {
430
+ const prefixes = [primaryPrefix];
431
+ if (!prefixes.includes(DEFAULT_COOKIE_PREFIX)) {
432
+ prefixes.push(DEFAULT_COOKIE_PREFIX);
433
+ }
434
+ if (!prefixes.includes(LEGACY_COOKIE_PREFIX)) {
435
+ prefixes.push(LEGACY_COOKIE_PREFIX);
436
+ }
437
+ return prefixes;
438
+ }
439
+ function createError(message) {
440
+ return new Error(`@xylex-group/athena/cookies: ${message}`);
441
+ }
442
+ function getSecretOrThrow(secret) {
443
+ const resolved = secret || getEnvironmentSecret();
444
+ if (!resolved) {
445
+ throw createError(
446
+ "getCookieCache requires a secret. Pass `secret` or set ATHENA_AUTH_SECRET/BETTER_AUTH_SECRET/AUTH_SECRET."
447
+ );
448
+ }
449
+ return resolved;
450
+ }
451
+ function asObject(value) {
452
+ if (!value || typeof value !== "object") {
453
+ return null;
454
+ }
455
+ return value;
456
+ }
457
+ function getSessionTokenFromPair(session) {
458
+ const token = session.session?.token;
459
+ if (typeof token !== "string" || token.length === 0) {
460
+ throw createError("setSessionCookie requires `session.session.token` to be a non-empty string.");
461
+ }
462
+ return token;
463
+ }
464
+ async function resolveCookieVersion(versionConfig, session, user) {
465
+ if (!versionConfig) {
466
+ return "1";
467
+ }
468
+ if (typeof versionConfig === "string") {
469
+ return versionConfig;
470
+ }
471
+ return versionConfig(session, user);
472
+ }
473
+ function getSessionCookieCacheName(cookiePrefix, cookieName, isSecure) {
474
+ return isSecure ? `${SECURE_COOKIE_PREFIX}${cookiePrefix}.${cookieName}` : `${cookiePrefix}.${cookieName}`;
475
+ }
476
+ async function setCookieValue(ctx, name, value, attributes) {
477
+ const secret = ctx.context.secret;
478
+ if (secret && typeof ctx.setSignedCookie === "function") {
479
+ await ctx.setSignedCookie(name, value, secret, attributes);
480
+ return;
481
+ }
482
+ ctx.setCookie(name, value, attributes);
483
+ }
484
+ function parseJsonSafely(value) {
485
+ try {
486
+ return JSON.parse(value);
487
+ } catch {
488
+ return null;
489
+ }
490
+ }
491
+ function getIsSecureCookie(config) {
492
+ if (config?.isSecure !== void 0) {
493
+ return config.isSecure;
494
+ }
495
+ return isProductionRuntime();
496
+ }
497
+ function createCookieGetter(options) {
498
+ const baseURLString = typeof options.baseURL === "string" ? options.baseURL : void 0;
499
+ const dynamicProtocol = typeof options.baseURL === "object" && options.baseURL !== null ? options.baseURL.protocol : void 0;
500
+ const secure = options.advanced?.useSecureCookies !== void 0 ? options.advanced.useSecureCookies : dynamicProtocol === "https" ? true : dynamicProtocol === "http" ? false : baseURLString ? baseURLString.startsWith("https://") : isProductionRuntime();
501
+ const secureCookiePrefix = secure ? SECURE_COOKIE_PREFIX : "";
502
+ const crossSubdomainEnabled = !!options.advanced?.crossSubDomainCookies?.enabled;
503
+ const domain = crossSubdomainEnabled ? options.advanced?.crossSubDomainCookies?.domain || (baseURLString ? new URL(baseURLString).hostname : void 0) : void 0;
504
+ if (crossSubdomainEnabled && !domain && !isDynamicBaseURLConfig(options.baseURL)) {
505
+ throw createError("baseURL is required when `crossSubDomainCookies.enabled` is true.");
506
+ }
507
+ function createCookie(cookieName, overrideAttributes = {}) {
508
+ const prefix = options.advanced?.cookiePrefix || DEFAULT_COOKIE_PREFIX;
509
+ const name = options.advanced?.cookies?.[cookieName]?.name || `${prefix}.${cookieName}`;
510
+ const attributes = options.advanced?.cookies?.[cookieName]?.attributes || {};
511
+ return {
512
+ name: `${secureCookiePrefix}${name}`,
513
+ attributes: {
514
+ secure: !!secureCookiePrefix,
515
+ sameSite: "lax",
516
+ path: "/",
517
+ httpOnly: true,
518
+ ...crossSubdomainEnabled ? { domain } : {},
519
+ ...options.advanced?.defaultCookieAttributes,
520
+ ...overrideAttributes,
521
+ ...attributes
522
+ }
523
+ };
524
+ }
525
+ return createCookie;
526
+ }
527
+ function getCookies(options) {
528
+ const createCookie = createCookieGetter(options);
529
+ const sessionToken = createCookie("session_token", { maxAge: options.session?.expiresIn || DEFAULT_SESSION_MAX_AGE });
530
+ const sessionData = createCookie("session_data", { maxAge: options.session?.cookieCache?.maxAge || DEFAULT_CACHE_MAX_AGE });
531
+ const accountData = createCookie("account_data", { maxAge: options.session?.cookieCache?.maxAge || DEFAULT_CACHE_MAX_AGE });
532
+ const dontRememberToken = createCookie("dont_remember");
533
+ return {
534
+ sessionToken: {
535
+ name: sessionToken.name,
536
+ attributes: sessionToken.attributes
537
+ },
538
+ sessionData: {
539
+ name: sessionData.name,
540
+ attributes: sessionData.attributes
541
+ },
542
+ dontRememberToken: {
543
+ name: dontRememberToken.name,
544
+ attributes: dontRememberToken.attributes
545
+ },
546
+ accountData: {
547
+ name: accountData.name,
548
+ attributes: accountData.attributes
549
+ }
550
+ };
551
+ }
552
+ async function setCookieCache(ctx, session, dontRememberMe) {
553
+ const cookieCacheConfig = ctx.context.options?.session?.cookieCache;
554
+ if (!cookieCacheConfig?.enabled) {
555
+ return;
556
+ }
557
+ const version = await resolveCookieVersion(
558
+ cookieCacheConfig.version,
559
+ session.session,
560
+ session.user
561
+ );
562
+ const sessionData = {
563
+ session: session.session,
564
+ user: session.user,
565
+ updatedAt: Date.now(),
566
+ version
567
+ };
568
+ const baseAttributes = ctx.context.authCookies.sessionData.attributes;
569
+ const maxAge = dontRememberMe ? void 0 : baseAttributes.maxAge;
570
+ const options = {
571
+ ...baseAttributes,
572
+ maxAge
573
+ };
574
+ const expiresAt = Date.now() + (options.maxAge || 60) * 1e3;
575
+ const strategy = cookieCacheConfig.strategy || "compact";
576
+ const secret = getSecretOrThrow(ctx.context.secret);
577
+ let encoded;
578
+ if (strategy === "jwt") {
579
+ encoded = await signJwtHS256(sessionData, secret, options.maxAge || DEFAULT_CACHE_MAX_AGE);
580
+ } else if (strategy === "jwe") {
581
+ throw createError("`jwe` strategy is not supported by the SDK cookie helper.");
582
+ } else {
583
+ const signature = await signHmacBase64Url(
584
+ secret,
585
+ JSON.stringify({
586
+ ...sessionData,
587
+ expiresAt
588
+ })
589
+ );
590
+ encoded = encodeStringToBase64Url(
591
+ JSON.stringify({
592
+ session: sessionData,
593
+ expiresAt,
594
+ signature
595
+ })
596
+ );
597
+ }
598
+ if (encoded.length > 4093) {
599
+ const store = createSessionStore(ctx.context.authCookies.sessionData.name, options, ctx);
600
+ const cookies = store.chunk(encoded, options);
601
+ store.setCookies(cookies);
602
+ } else {
603
+ const store = createSessionStore(ctx.context.authCookies.sessionData.name, options, ctx);
604
+ if (store.hasChunks()) {
605
+ store.setCookies(store.clean());
606
+ }
607
+ ctx.setCookie(ctx.context.authCookies.sessionData.name, encoded, options);
608
+ }
609
+ }
610
+ async function setSessionCookie(ctx, session, dontRememberMe, overrides) {
611
+ if (dontRememberMe === void 0 && typeof ctx.getSignedCookie === "function" && ctx.context.secret) {
612
+ const existingFlag = await ctx.getSignedCookie(ctx.context.authCookies.dontRememberToken.name, ctx.context.secret);
613
+ dontRememberMe = !!existingFlag;
614
+ }
615
+ const resolvedDontRememberMe = dontRememberMe ?? false;
616
+ const token = getSessionTokenFromPair(session);
617
+ const options = ctx.context.authCookies.sessionToken.attributes;
618
+ const maxAge = resolvedDontRememberMe ? void 0 : ctx.context.sessionConfig?.expiresIn;
619
+ await setCookieValue(ctx, ctx.context.authCookies.sessionToken.name, token, {
620
+ ...options,
621
+ maxAge,
622
+ ...overrides
623
+ });
624
+ if (resolvedDontRememberMe) {
625
+ await setCookieValue(
626
+ ctx,
627
+ ctx.context.authCookies.dontRememberToken.name,
628
+ "true",
629
+ ctx.context.authCookies.dontRememberToken.attributes
630
+ );
631
+ }
632
+ await setCookieCache(ctx, session, resolvedDontRememberMe);
633
+ ctx.context.setNewSession?.(session);
634
+ }
635
+ function expireCookie(ctx, cookie) {
636
+ ctx.setCookie(cookie.name, "", {
637
+ ...cookie.attributes,
638
+ maxAge: 0
639
+ });
640
+ }
641
+ function deleteSessionCookie(ctx, skipDontRememberMe) {
642
+ expireCookie(ctx, ctx.context.authCookies.sessionToken);
643
+ expireCookie(ctx, ctx.context.authCookies.sessionData);
644
+ if (ctx.context.options?.account?.storeAccountCookie) {
645
+ expireCookie(ctx, ctx.context.authCookies.accountData);
646
+ const accountStore = createAccountStore(
647
+ ctx.context.authCookies.accountData.name,
648
+ ctx.context.authCookies.accountData.attributes,
649
+ ctx
650
+ );
651
+ accountStore.setCookies(accountStore.clean());
652
+ }
653
+ const sessionStore = createSessionStore(
654
+ ctx.context.authCookies.sessionData.name,
655
+ ctx.context.authCookies.sessionData.attributes,
656
+ ctx
657
+ );
658
+ sessionStore.setCookies(sessionStore.clean());
659
+ if (!skipDontRememberMe) {
660
+ expireCookie(ctx, ctx.context.authCookies.dontRememberToken);
661
+ }
662
+ }
141
663
  var getSessionCookie = (request, config) => {
142
664
  const cookies = (request instanceof Headers || !("headers" in request) ? request : request.headers).get("cookie");
143
665
  if (!cookies) {
144
666
  return null;
145
667
  }
146
- const { cookieName = "session_token", cookiePrefix = "athena-auth" } = {};
668
+ const { cookieName = "session_token", cookiePrefix = "athena-auth" } = config || {};
147
669
  const parsedCookie = parseCookies(cookies);
148
670
  const getCookie = (name) => parsedCookie.get(name) || parsedCookie.get(`${SECURE_COOKIE_PREFIX}${name}`);
149
671
  const sessionToken = getCookie(`${cookiePrefix}.${cookieName}`) || getCookie(`${cookiePrefix}-${cookieName}`);
@@ -152,10 +674,126 @@ var getSessionCookie = (request, config) => {
152
674
  }
153
675
  return null;
154
676
  };
677
+ var getCookieCache = async (request, config) => {
678
+ const headers = request instanceof Headers || !("headers" in request) ? request : request.headers;
679
+ const cookieHeader = headers.get("cookie");
680
+ if (!cookieHeader) {
681
+ return null;
682
+ }
683
+ const parsedCookie = parseCookies(cookieHeader);
684
+ const cookieName = config?.cookieName || "session_data";
685
+ const requestedPrefix = config?.cookiePrefix || DEFAULT_COOKIE_PREFIX;
686
+ const strategy = config?.strategy || "compact";
687
+ const cookiePrefixes = resolveCookiePrefixes(requestedPrefix);
688
+ const isSecure = getIsSecureCookie(config);
689
+ const secret = getSecretOrThrow(config?.secret);
690
+ let sessionData;
691
+ for (const prefix of cookiePrefixes) {
692
+ const candidate = getSessionCookieCacheName(prefix, cookieName, isSecure);
693
+ const cookieValue = parsedCookie.get(candidate);
694
+ if (cookieValue) {
695
+ sessionData = cookieValue;
696
+ break;
697
+ }
698
+ }
699
+ if (!sessionData) {
700
+ const reconstructedChunks = [];
701
+ for (const prefix of cookiePrefixes) {
702
+ const candidate = getSessionCookieCacheName(prefix, cookieName, isSecure);
703
+ for (const [name, value] of parsedCookie.entries()) {
704
+ if (!name.startsWith(`${candidate}.`)) {
705
+ continue;
706
+ }
707
+ const parts = name.split(".");
708
+ const indexStr = parts[parts.length - 1];
709
+ const index = parseInt(indexStr || "0", 10);
710
+ if (!Number.isNaN(index)) {
711
+ reconstructedChunks.push({ index, value });
712
+ }
713
+ }
714
+ if (reconstructedChunks.length > 0) {
715
+ break;
716
+ }
717
+ }
718
+ if (reconstructedChunks.length > 0) {
719
+ reconstructedChunks.sort((left, right) => left.index - right.index);
720
+ sessionData = reconstructedChunks.map((chunk) => chunk.value).join("");
721
+ }
722
+ }
723
+ if (!sessionData) {
724
+ return null;
725
+ }
726
+ if (strategy === "jwe") {
727
+ throw createError(
728
+ "`jwe` strategy is not supported by the SDK cookie helper. Use compact/jwt or pass cookie data through the auth server."
729
+ );
730
+ }
731
+ if (strategy === "jwt") {
732
+ const payload = await verifyJwtHS256(sessionData, secret);
733
+ if (!payload) {
734
+ return null;
735
+ }
736
+ const sessionRecord = asObject(payload.session);
737
+ const userRecord = asObject(payload.user);
738
+ const updatedAt = payload.updatedAt;
739
+ if (!sessionRecord || !userRecord || typeof updatedAt !== "number") {
740
+ return null;
741
+ }
742
+ if (config?.version) {
743
+ const cookieVersion = typeof payload.version === "string" ? payload.version : "1";
744
+ const expectedVersion = typeof config.version === "string" ? config.version : await config.version(sessionRecord, userRecord);
745
+ if (cookieVersion !== expectedVersion) {
746
+ return null;
747
+ }
748
+ }
749
+ return {
750
+ session: sessionRecord,
751
+ user: userRecord,
752
+ updatedAt,
753
+ version: typeof payload.version === "string" ? payload.version : void 0
754
+ };
755
+ }
756
+ const compactPayload = parseJsonSafely(decodeBase64UrlToString(sessionData));
757
+ if (!compactPayload) {
758
+ return null;
759
+ }
760
+ const expectedSignature = await signHmacBase64Url(
761
+ secret,
762
+ JSON.stringify({
763
+ ...compactPayload.session,
764
+ expiresAt: compactPayload.expiresAt
765
+ })
766
+ );
767
+ if (expectedSignature !== compactPayload.signature) {
768
+ return null;
769
+ }
770
+ if (compactPayload.expiresAt <= Date.now()) {
771
+ return null;
772
+ }
773
+ const resolvedSession = compactPayload.session;
774
+ if (config?.version) {
775
+ const cookieVersion = resolvedSession.version || "1";
776
+ const expectedVersion = typeof config.version === "string" ? config.version : await config.version(resolvedSession.session, resolvedSession.user);
777
+ if (cookieVersion !== expectedVersion) {
778
+ return null;
779
+ }
780
+ }
781
+ const sessionObject = asObject(resolvedSession.session);
782
+ const userObject = asObject(resolvedSession.user);
783
+ if (!sessionObject || !userObject) {
784
+ return null;
785
+ }
786
+ return {
787
+ session: sessionObject,
788
+ user: userObject,
789
+ updatedAt: resolvedSession.updatedAt,
790
+ version: resolvedSession.version
791
+ };
792
+ };
155
793
 
156
794
  // package.json
157
795
  var package_default = {
158
- version: "2.4.1"
796
+ version: "2.6.0"
159
797
  };
160
798
 
161
799
  // src/sdk-version.ts
@@ -2696,38 +3334,730 @@ async function withRetry(config, fn) {
2696
3334
  await sleep(delay);
2697
3335
  }
2698
3336
  }
2699
- throw new Error("withRetry reached an unexpected state");
3337
+ throw new Error("withRetry reached an unexpected state");
3338
+ }
3339
+
3340
+ // src/db/module.ts
3341
+ function createDbModule(input) {
3342
+ const db = {
3343
+ from(table, options) {
3344
+ return input.from(table, options);
3345
+ },
3346
+ select(table, columns, options) {
3347
+ return input.from(table).select(columns, options);
3348
+ },
3349
+ insert(table, values, options) {
3350
+ return Array.isArray(values) ? input.from(table).insert(values, options) : input.from(table).insert(values, options);
3351
+ },
3352
+ upsert(table, values, options) {
3353
+ return Array.isArray(values) ? input.from(table).upsert(values, options) : input.from(table).upsert(values, options);
3354
+ },
3355
+ update(table, values, options) {
3356
+ return input.from(table).update(values, options);
3357
+ },
3358
+ delete(table, options) {
3359
+ return input.from(table).delete(options);
3360
+ },
3361
+ rpc(fn, args, options) {
3362
+ return input.rpc(fn, args, options);
3363
+ },
3364
+ query(query, options) {
3365
+ return input.query(query, options);
3366
+ }
3367
+ };
3368
+ return db;
3369
+ }
3370
+
3371
+ // src/storage/module.ts
3372
+ var storageSdkManifest = {
3373
+ namespace: "storage",
3374
+ basePath: "/storage",
3375
+ envelopeKinds: {
3376
+ raw: "response body is the payload",
3377
+ athena: "response body is { status, message, data }"
3378
+ },
3379
+ methods: [
3380
+ {
3381
+ name: "listStorageCatalogs",
3382
+ method: "GET",
3383
+ path: "/storage/catalogs",
3384
+ responseEnvelope: "raw",
3385
+ responseType: "{ data: S3CatalogItem[] }"
3386
+ },
3387
+ {
3388
+ name: "createStorageCatalog",
3389
+ method: "POST",
3390
+ path: "/storage/catalogs",
3391
+ requestType: "CreateStorageCatalogRequest",
3392
+ responseEnvelope: "raw",
3393
+ responseType: "S3CatalogItem"
3394
+ },
3395
+ {
3396
+ name: "updateStorageCatalog",
3397
+ method: "PATCH",
3398
+ path: "/storage/catalogs/{id}",
3399
+ pathParams: ["id"],
3400
+ requestType: "UpdateStorageCatalogRequest",
3401
+ responseEnvelope: "raw",
3402
+ responseType: "S3CatalogItem"
3403
+ },
3404
+ {
3405
+ name: "deleteStorageCatalog",
3406
+ method: "DELETE",
3407
+ path: "/storage/catalogs/{id}",
3408
+ pathParams: ["id"],
3409
+ responseEnvelope: "raw",
3410
+ responseType: "{ id: string; deleted: boolean }"
3411
+ },
3412
+ {
3413
+ name: "listStorageCredentials",
3414
+ method: "GET",
3415
+ path: "/storage/credentials",
3416
+ responseEnvelope: "raw",
3417
+ responseType: "{ data: S3CredentialListItem[] }"
3418
+ },
3419
+ {
3420
+ name: "createStorageUploadUrl",
3421
+ method: "POST",
3422
+ path: "/storage/files/upload-url",
3423
+ requestType: "CreateStorageUploadUrlRequest",
3424
+ responseEnvelope: "athena",
3425
+ responseType: "StorageUploadUrlResponse"
3426
+ },
3427
+ {
3428
+ name: "createStorageUploadUrls",
3429
+ method: "POST",
3430
+ path: "/storage/files/upload-urls",
3431
+ requestType: "CreateStorageUploadUrlsRequest",
3432
+ responseEnvelope: "athena",
3433
+ responseType: "StorageBatchUploadUrlResponse"
3434
+ },
3435
+ {
3436
+ name: "listStorageFiles",
3437
+ method: "POST",
3438
+ path: "/storage/files/list",
3439
+ requestType: "ListStorageFilesRequest",
3440
+ responseEnvelope: "athena",
3441
+ responseType: "StorageListFilesResponse"
3442
+ },
3443
+ {
3444
+ name: "getStorageFile",
3445
+ method: "GET",
3446
+ path: "/storage/files/{file_id}",
3447
+ pathParams: ["file_id"],
3448
+ responseEnvelope: "athena",
3449
+ responseType: "StorageFileMutationResponse"
3450
+ },
3451
+ {
3452
+ name: "getStorageFileUrl",
3453
+ method: "GET",
3454
+ path: "/storage/files/{file_id}/url",
3455
+ pathParams: ["file_id"],
3456
+ queryParams: ["purpose"],
3457
+ responseEnvelope: "athena",
3458
+ responseType: "PresignedFileUrlResponse"
3459
+ },
3460
+ {
3461
+ name: "getStorageFileProxy",
3462
+ method: "GET",
3463
+ path: "/storage/files/{file_id}/proxy",
3464
+ pathParams: ["file_id"],
3465
+ queryParams: ["purpose"],
3466
+ responseEnvelope: "raw",
3467
+ responseType: "Response",
3468
+ binary: true
3469
+ },
3470
+ {
3471
+ name: "updateStorageFile",
3472
+ method: "PATCH",
3473
+ path: "/storage/files/{file_id}",
3474
+ pathParams: ["file_id"],
3475
+ requestType: "UpdateStorageFileRequest",
3476
+ responseEnvelope: "athena",
3477
+ responseType: "StorageFileMutationResponse"
3478
+ },
3479
+ {
3480
+ name: "deleteStorageFile",
3481
+ method: "DELETE",
3482
+ path: "/storage/files/{file_id}",
3483
+ pathParams: ["file_id"],
3484
+ responseEnvelope: "athena",
3485
+ responseType: "StorageFileMutationResponse"
3486
+ },
3487
+ {
3488
+ name: "setStorageFileVisibility",
3489
+ method: "PATCH",
3490
+ path: "/storage/files/{file_id}/visibility",
3491
+ pathParams: ["file_id"],
3492
+ requestType: "SetStorageFileVisibilityRequest",
3493
+ responseEnvelope: "athena",
3494
+ responseType: "StorageFileMutationResponse"
3495
+ },
3496
+ {
3497
+ name: "deleteStorageFolder",
3498
+ method: "POST",
3499
+ path: "/storage/folders/delete",
3500
+ requestType: "DeleteStorageFolderRequest",
3501
+ responseEnvelope: "athena",
3502
+ responseType: "StorageFolderMutationResponse"
3503
+ },
3504
+ {
3505
+ name: "moveStorageFolder",
3506
+ method: "POST",
3507
+ path: "/storage/folders/move",
3508
+ requestType: "MoveStorageFolderRequest",
3509
+ responseEnvelope: "athena",
3510
+ responseType: "StorageFolderMutationResponse"
3511
+ }
3512
+ ]
3513
+ };
3514
+ var AthenaStorageErrorCode = {
3515
+ InvalidUrl: "INVALID_URL",
3516
+ NetworkError: "NETWORK_ERROR",
3517
+ HttpError: "HTTP_ERROR",
3518
+ InvalidJson: "INVALID_JSON",
3519
+ InvalidAthenaEnvelope: "INVALID_ATHENA_ENVELOPE",
3520
+ UnknownError: "UNKNOWN_ERROR"
3521
+ };
3522
+ var AthenaStorageError = class extends Error {
3523
+ code;
3524
+ athenaCode;
3525
+ kind;
3526
+ category;
3527
+ retryable;
3528
+ status;
3529
+ endpoint;
3530
+ method;
3531
+ requestId;
3532
+ hint;
3533
+ causeDetail;
3534
+ raw;
3535
+ normalized;
3536
+ __athenaNormalizedError;
3537
+ constructor(input) {
3538
+ super(input.message, { cause: input.cause });
3539
+ this.name = "AthenaStorageError";
3540
+ this.code = input.code;
3541
+ this.status = input.status;
3542
+ this.endpoint = input.endpoint;
3543
+ this.method = input.method;
3544
+ this.requestId = input.requestId;
3545
+ this.hint = input.hint;
3546
+ this.causeDetail = causeToString(input.cause);
3547
+ this.raw = input.raw ?? null;
3548
+ this.normalized = normalizeStorageErrorInput(input);
3549
+ this.__athenaNormalizedError = this.normalized;
3550
+ this.athenaCode = this.normalized.code;
3551
+ this.kind = this.normalized.kind;
3552
+ this.category = this.normalized.category;
3553
+ this.retryable = this.normalized.retryable;
3554
+ Object.defineProperty(this, "__athenaNormalizedError", {
3555
+ value: this.normalized,
3556
+ enumerable: false,
3557
+ configurable: false,
3558
+ writable: false
3559
+ });
3560
+ }
3561
+ toDetails() {
3562
+ return {
3563
+ code: this.code,
3564
+ athenaCode: this.athenaCode,
3565
+ kind: this.kind,
3566
+ category: this.category,
3567
+ retryable: this.retryable,
3568
+ message: this.message,
3569
+ status: this.status,
3570
+ endpoint: this.endpoint,
3571
+ method: this.method,
3572
+ requestId: this.requestId,
3573
+ hint: this.hint,
3574
+ cause: this.causeDetail,
3575
+ raw: this.raw
3576
+ };
3577
+ }
3578
+ };
3579
+ function isRecord5(value) {
3580
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
3581
+ }
3582
+ function causeToString(cause) {
3583
+ if (cause === void 0 || cause === null) return void 0;
3584
+ if (typeof cause === "string") return cause;
3585
+ if (cause instanceof Error && cause.message.trim()) return cause.message.trim();
3586
+ try {
3587
+ return JSON.stringify(cause);
3588
+ } catch {
3589
+ return String(cause);
3590
+ }
3591
+ }
3592
+ function storageGatewayCode(code) {
3593
+ if (code === "INVALID_URL") return "INVALID_URL";
3594
+ if (code === "NETWORK_ERROR") return "NETWORK_ERROR";
3595
+ if (code === "INVALID_JSON" || code === "INVALID_ATHENA_ENVELOPE") return "INVALID_JSON";
3596
+ if (code === "HTTP_ERROR") return "HTTP_ERROR";
3597
+ return "UNKNOWN_ERROR";
3598
+ }
3599
+ function headerValue(headers, names) {
3600
+ for (const name of names) {
3601
+ const value = headers.get(name);
3602
+ if (value?.trim()) return value.trim();
3603
+ }
3604
+ return void 0;
3605
+ }
3606
+ function storageOperationFromEndpoint(endpoint, method) {
3607
+ const endpointPath = String(endpoint).split("?")[0];
3608
+ for (const candidate of storageSdkManifest.methods) {
3609
+ if (candidate.method !== method) continue;
3610
+ const pattern = `^${candidate.path.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\\\{[^/]+\\\}/g, "[^/]+")}$`;
3611
+ if (new RegExp(pattern).test(endpointPath)) {
3612
+ return candidate.name;
3613
+ }
3614
+ }
3615
+ return `storage:${method.toLowerCase()}`;
3616
+ }
3617
+ function normalizeStorageErrorInput(input) {
3618
+ return normalizeAthenaError(
3619
+ {
3620
+ data: null,
3621
+ error: {
3622
+ message: input.message,
3623
+ gatewayCode: storageGatewayCode(input.code),
3624
+ status: input.status,
3625
+ raw: input.raw ?? input.cause ?? null
3626
+ },
3627
+ errorDetails: {
3628
+ code: storageGatewayCode(input.code),
3629
+ message: input.message,
3630
+ status: input.status,
3631
+ endpoint: input.endpoint,
3632
+ method: input.method,
3633
+ requestId: input.requestId,
3634
+ hint: input.hint,
3635
+ cause: causeToString(input.cause)
3636
+ },
3637
+ raw: input.raw ?? input.cause ?? null,
3638
+ status: input.status
3639
+ },
3640
+ { operation: storageOperationFromEndpoint(input.endpoint, input.method) }
3641
+ );
3642
+ }
3643
+ function createAthenaStorageError(input) {
3644
+ return new AthenaStorageError(input);
3645
+ }
3646
+ async function notifyStorageError(error, options, runtimeOptions) {
3647
+ const handlers = [runtimeOptions?.onError, options?.onError].filter(
3648
+ (handler) => typeof handler === "function"
3649
+ );
3650
+ for (const handler of handlers) {
3651
+ try {
3652
+ await handler(error);
3653
+ } catch {
3654
+ }
3655
+ }
3656
+ }
3657
+ async function rejectStorageError(input, options, runtimeOptions) {
3658
+ const error = createAthenaStorageError(input);
3659
+ await notifyStorageError(error, options, runtimeOptions);
3660
+ throw error;
3661
+ }
3662
+ function parseResponseBody3(rawText, contentType) {
3663
+ if (!rawText) {
3664
+ return { parsed: null, parseFailed: false };
3665
+ }
3666
+ const contentTypeSuggestsJson = contentType?.toLowerCase().includes("application/json") ?? false;
3667
+ const looksJson = contentTypeSuggestsJson || rawText.startsWith("{") || rawText.startsWith("[");
3668
+ if (!looksJson) {
3669
+ return { parsed: rawText, parseFailed: false };
3670
+ }
3671
+ try {
3672
+ return { parsed: JSON.parse(rawText), parseFailed: false };
3673
+ } catch {
3674
+ return { parsed: rawText, parseFailed: true };
3675
+ }
3676
+ }
3677
+ function appendQuery(path, query) {
3678
+ if (!query) return path;
3679
+ const params = new URLSearchParams();
3680
+ for (const [key, value] of Object.entries(query)) {
3681
+ if (value === void 0 || value === null) continue;
3682
+ params.set(key, String(value));
3683
+ }
3684
+ const queryText = params.toString();
3685
+ return queryText ? `${path}?${queryText}` : path;
3686
+ }
3687
+ function storagePath(path) {
3688
+ return path;
3689
+ }
3690
+ function withPathParam(path, name, value) {
3691
+ return path.replace(`{${name}}`, encodeURIComponent(value));
3692
+ }
3693
+ function resolveErrorMessage3(payload, fallback) {
3694
+ if (isRecord5(payload)) {
3695
+ const message = payload.message ?? payload.error ?? payload.details;
3696
+ if (typeof message === "string" && message.trim()) {
3697
+ return message.trim();
3698
+ }
3699
+ }
3700
+ if (typeof payload === "string" && payload.trim()) {
3701
+ return payload.trim();
3702
+ }
3703
+ return fallback;
3704
+ }
3705
+ function resolveErrorHint2(payload) {
3706
+ if (!isRecord5(payload)) return void 0;
3707
+ const hint = payload.hint ?? payload.suggestion;
3708
+ return typeof hint === "string" && hint.trim() ? hint.trim() : void 0;
3709
+ }
3710
+ function resolveErrorCause(payload) {
3711
+ if (!isRecord5(payload)) return void 0;
3712
+ const cause = payload.cause ?? payload.reason;
3713
+ return typeof cause === "string" && cause.trim() ? cause.trim() : void 0;
3714
+ }
3715
+ function storageCodeFromUnknown(error) {
3716
+ if (isAthenaGatewayError(error)) {
3717
+ if (error.code === "INVALID_URL") return "INVALID_URL";
3718
+ if (error.code === "NETWORK_ERROR") return "NETWORK_ERROR";
3719
+ if (error.code === "INVALID_JSON") return "INVALID_JSON";
3720
+ if (error.code === "HTTP_ERROR") return "HTTP_ERROR";
3721
+ }
3722
+ return "UNKNOWN_ERROR";
3723
+ }
3724
+ async function callStorageEndpoint(gateway, endpoint, method, envelope, payload, options, runtimeOptions) {
3725
+ let url;
3726
+ let headers;
3727
+ try {
3728
+ const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : gateway.baseUrl;
3729
+ url = buildAthenaGatewayUrl(baseUrl, endpoint);
3730
+ headers = gateway.buildHeaders(options);
3731
+ } catch (error) {
3732
+ return rejectStorageError(
3733
+ {
3734
+ code: storageCodeFromUnknown(error),
3735
+ message: error instanceof Error ? error.message : `Athena storage ${method} ${endpoint} failed before sending the request`,
3736
+ status: isAthenaGatewayError(error) ? error.status : 0,
3737
+ endpoint,
3738
+ method,
3739
+ raw: error,
3740
+ requestId: isAthenaGatewayError(error) ? error.requestId : void 0,
3741
+ hint: isAthenaGatewayError(error) ? error.hint : void 0,
3742
+ cause: error
3743
+ },
3744
+ options,
3745
+ runtimeOptions
3746
+ );
3747
+ }
3748
+ const requestInit = {
3749
+ method,
3750
+ headers,
3751
+ signal: options?.signal
3752
+ };
3753
+ if (payload !== void 0 && method !== "GET") {
3754
+ requestInit.body = JSON.stringify(payload);
3755
+ }
3756
+ let response;
3757
+ try {
3758
+ response = await fetch(url, requestInit);
3759
+ } catch (error) {
3760
+ const message = error instanceof Error ? error.message : String(error);
3761
+ return rejectStorageError(
3762
+ {
3763
+ code: "NETWORK_ERROR",
3764
+ message: `Network error while calling Athena storage ${method} ${endpoint}: ${message}`,
3765
+ status: 0,
3766
+ endpoint,
3767
+ method,
3768
+ cause: error
3769
+ },
3770
+ options,
3771
+ runtimeOptions
3772
+ );
3773
+ }
3774
+ let rawText;
3775
+ try {
3776
+ rawText = await response.text();
3777
+ } catch (error) {
3778
+ return rejectStorageError(
3779
+ {
3780
+ code: "NETWORK_ERROR",
3781
+ message: `Athena storage ${method} ${endpoint} response body could not be read`,
3782
+ status: response.status,
3783
+ endpoint,
3784
+ method,
3785
+ requestId: headerValue(response.headers, ["x-athena-request-id", "x-request-id", "request-id"]),
3786
+ cause: error
3787
+ },
3788
+ options,
3789
+ runtimeOptions
3790
+ );
3791
+ }
3792
+ const parsedBody = parseResponseBody3(rawText ?? "", response.headers.get("content-type"));
3793
+ const requestId = headerValue(response.headers, ["x-athena-request-id", "x-request-id", "request-id"]);
3794
+ if (parsedBody.parseFailed) {
3795
+ return rejectStorageError(
3796
+ {
3797
+ code: "INVALID_JSON",
3798
+ message: `Athena storage ${method} ${endpoint} returned malformed JSON`,
3799
+ status: response.status,
3800
+ endpoint,
3801
+ method,
3802
+ requestId,
3803
+ raw: parsedBody.parsed
3804
+ },
3805
+ options,
3806
+ runtimeOptions
3807
+ );
3808
+ }
3809
+ if (!response.ok) {
3810
+ return rejectStorageError(
3811
+ {
3812
+ code: "HTTP_ERROR",
3813
+ message: resolveErrorMessage3(
3814
+ parsedBody.parsed,
3815
+ `Athena storage ${method} ${endpoint} failed with status ${response.status}`
3816
+ ),
3817
+ status: response.status,
3818
+ endpoint,
3819
+ method,
3820
+ requestId,
3821
+ hint: resolveErrorHint2(parsedBody.parsed),
3822
+ cause: resolveErrorCause(parsedBody.parsed),
3823
+ raw: parsedBody.parsed
3824
+ },
3825
+ options,
3826
+ runtimeOptions
3827
+ );
3828
+ }
3829
+ if (envelope === "athena") {
3830
+ if (!isRecord5(parsedBody.parsed) || !("data" in parsedBody.parsed)) {
3831
+ return rejectStorageError(
3832
+ {
3833
+ code: "INVALID_ATHENA_ENVELOPE",
3834
+ message: `Athena storage ${method} ${endpoint} returned an invalid Athena envelope`,
3835
+ status: response.status,
3836
+ endpoint,
3837
+ method,
3838
+ requestId,
3839
+ raw: parsedBody.parsed
3840
+ },
3841
+ options,
3842
+ runtimeOptions
3843
+ );
3844
+ }
3845
+ return parsedBody.parsed.data;
3846
+ }
3847
+ return parsedBody.parsed;
3848
+ }
3849
+ async function callStorageBinaryEndpoint(gateway, endpoint, method, options, runtimeOptions) {
3850
+ let url;
3851
+ let headers;
3852
+ try {
3853
+ const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : gateway.baseUrl;
3854
+ url = buildAthenaGatewayUrl(baseUrl, endpoint);
3855
+ headers = gateway.buildHeaders(options);
3856
+ } catch (error) {
3857
+ return rejectStorageError(
3858
+ {
3859
+ code: storageCodeFromUnknown(error),
3860
+ message: error instanceof Error ? error.message : `Athena storage ${method} ${endpoint} failed before sending the request`,
3861
+ status: isAthenaGatewayError(error) ? error.status : 0,
3862
+ endpoint,
3863
+ method,
3864
+ raw: error,
3865
+ requestId: isAthenaGatewayError(error) ? error.requestId : void 0,
3866
+ hint: isAthenaGatewayError(error) ? error.hint : void 0,
3867
+ cause: error
3868
+ },
3869
+ options,
3870
+ runtimeOptions
3871
+ );
3872
+ }
3873
+ let response;
3874
+ try {
3875
+ response = await fetch(url, {
3876
+ method,
3877
+ headers,
3878
+ signal: options?.signal
3879
+ });
3880
+ } catch (error) {
3881
+ const message = error instanceof Error ? error.message : String(error);
3882
+ return rejectStorageError(
3883
+ {
3884
+ code: "NETWORK_ERROR",
3885
+ message: `Network error while calling Athena storage ${method} ${endpoint}: ${message}`,
3886
+ status: 0,
3887
+ endpoint,
3888
+ method,
3889
+ cause: error
3890
+ },
3891
+ options,
3892
+ runtimeOptions
3893
+ );
3894
+ }
3895
+ if (response.ok) {
3896
+ return response;
3897
+ }
3898
+ const requestId = headerValue(response.headers, ["x-athena-request-id", "x-request-id", "request-id"]);
3899
+ let rawErrorBody = null;
3900
+ try {
3901
+ const rawText = await response.text();
3902
+ const parsedBody = parseResponseBody3(rawText ?? "", response.headers.get("content-type"));
3903
+ rawErrorBody = parsedBody.parsed;
3904
+ } catch (error) {
3905
+ return rejectStorageError(
3906
+ {
3907
+ code: "NETWORK_ERROR",
3908
+ message: `Athena storage ${method} ${endpoint} error response body could not be read`,
3909
+ status: response.status,
3910
+ endpoint,
3911
+ method,
3912
+ requestId,
3913
+ cause: error
3914
+ },
3915
+ options,
3916
+ runtimeOptions
3917
+ );
3918
+ }
3919
+ return rejectStorageError(
3920
+ {
3921
+ code: "HTTP_ERROR",
3922
+ message: resolveErrorMessage3(
3923
+ rawErrorBody,
3924
+ `Athena storage ${method} ${endpoint} failed with status ${response.status}`
3925
+ ),
3926
+ status: response.status,
3927
+ endpoint,
3928
+ method,
3929
+ requestId,
3930
+ hint: resolveErrorHint2(rawErrorBody),
3931
+ cause: resolveErrorCause(rawErrorBody),
3932
+ raw: rawErrorBody
3933
+ },
3934
+ options,
3935
+ runtimeOptions
3936
+ );
2700
3937
  }
2701
-
2702
- // src/db/module.ts
2703
- function createDbModule(input) {
2704
- const db = {
2705
- from(table, options) {
2706
- return input.from(table, options);
3938
+ function createStorageModule(gateway, runtimeOptions) {
3939
+ return {
3940
+ listStorageCatalogs(options) {
3941
+ return callStorageEndpoint(gateway, storagePath("/storage/catalogs"), "GET", "raw", void 0, options, runtimeOptions);
2707
3942
  },
2708
- select(table, columns, options) {
2709
- return input.from(table).select(columns, options);
3943
+ createStorageCatalog(input, options) {
3944
+ return callStorageEndpoint(gateway, storagePath("/storage/catalogs"), "POST", "raw", input, options, runtimeOptions);
2710
3945
  },
2711
- insert(table, values, options) {
2712
- return Array.isArray(values) ? input.from(table).insert(values, options) : input.from(table).insert(values, options);
3946
+ updateStorageCatalog(id, input, options) {
3947
+ return callStorageEndpoint(
3948
+ gateway,
3949
+ storagePath(withPathParam("/storage/catalogs/{id}", "id", id)),
3950
+ "PATCH",
3951
+ "raw",
3952
+ input,
3953
+ options,
3954
+ runtimeOptions
3955
+ );
2713
3956
  },
2714
- upsert(table, values, options) {
2715
- return Array.isArray(values) ? input.from(table).upsert(values, options) : input.from(table).upsert(values, options);
3957
+ deleteStorageCatalog(id, options) {
3958
+ return callStorageEndpoint(
3959
+ gateway,
3960
+ storagePath(withPathParam("/storage/catalogs/{id}", "id", id)),
3961
+ "DELETE",
3962
+ "raw",
3963
+ void 0,
3964
+ options,
3965
+ runtimeOptions
3966
+ );
2716
3967
  },
2717
- update(table, values, options) {
2718
- return input.from(table).update(values, options);
3968
+ listStorageCredentials(options) {
3969
+ return callStorageEndpoint(gateway, storagePath("/storage/credentials"), "GET", "raw", void 0, options, runtimeOptions);
2719
3970
  },
2720
- delete(table, options) {
2721
- return input.from(table).delete(options);
3971
+ createStorageUploadUrl(input, options) {
3972
+ return callStorageEndpoint(
3973
+ gateway,
3974
+ storagePath("/storage/files/upload-url"),
3975
+ "POST",
3976
+ "athena",
3977
+ input,
3978
+ options,
3979
+ runtimeOptions
3980
+ );
2722
3981
  },
2723
- rpc(fn, args, options) {
2724
- return input.rpc(fn, args, options);
3982
+ createStorageUploadUrls(input, options) {
3983
+ return callStorageEndpoint(
3984
+ gateway,
3985
+ storagePath("/storage/files/upload-urls"),
3986
+ "POST",
3987
+ "athena",
3988
+ input,
3989
+ options,
3990
+ runtimeOptions
3991
+ );
2725
3992
  },
2726
- query(query, options) {
2727
- return input.query(query, options);
3993
+ listStorageFiles(input, options) {
3994
+ return callStorageEndpoint(gateway, storagePath("/storage/files/list"), "POST", "athena", input, options, runtimeOptions);
3995
+ },
3996
+ getStorageFile(fileId, options) {
3997
+ return callStorageEndpoint(
3998
+ gateway,
3999
+ storagePath(withPathParam("/storage/files/{file_id}", "file_id", fileId)),
4000
+ "GET",
4001
+ "athena",
4002
+ void 0,
4003
+ options,
4004
+ runtimeOptions
4005
+ );
4006
+ },
4007
+ getStorageFileUrl(fileId, query, options) {
4008
+ const path = appendQuery(
4009
+ withPathParam("/storage/files/{file_id}/url", "file_id", fileId),
4010
+ query
4011
+ );
4012
+ return callStorageEndpoint(gateway, storagePath(path), "GET", "athena", void 0, options, runtimeOptions);
4013
+ },
4014
+ getStorageFileProxy(fileId, query, options) {
4015
+ const path = appendQuery(
4016
+ withPathParam("/storage/files/{file_id}/proxy", "file_id", fileId),
4017
+ query
4018
+ );
4019
+ return callStorageBinaryEndpoint(gateway, storagePath(path), "GET", options, runtimeOptions);
4020
+ },
4021
+ updateStorageFile(fileId, input, options) {
4022
+ return callStorageEndpoint(
4023
+ gateway,
4024
+ storagePath(withPathParam("/storage/files/{file_id}", "file_id", fileId)),
4025
+ "PATCH",
4026
+ "athena",
4027
+ input,
4028
+ options,
4029
+ runtimeOptions
4030
+ );
4031
+ },
4032
+ deleteStorageFile(fileId, options) {
4033
+ return callStorageEndpoint(
4034
+ gateway,
4035
+ storagePath(withPathParam("/storage/files/{file_id}", "file_id", fileId)),
4036
+ "DELETE",
4037
+ "athena",
4038
+ void 0,
4039
+ options,
4040
+ runtimeOptions
4041
+ );
4042
+ },
4043
+ setStorageFileVisibility(fileId, input, options) {
4044
+ return callStorageEndpoint(
4045
+ gateway,
4046
+ storagePath(withPathParam("/storage/files/{file_id}/visibility", "file_id", fileId)),
4047
+ "PATCH",
4048
+ "athena",
4049
+ input,
4050
+ options,
4051
+ runtimeOptions
4052
+ );
4053
+ },
4054
+ deleteStorageFolder(input, options) {
4055
+ return callStorageEndpoint(gateway, storagePath("/storage/folders/delete"), "POST", "athena", input, options, runtimeOptions);
4056
+ },
4057
+ moveStorageFolder(input, options) {
4058
+ return callStorageEndpoint(gateway, storagePath("/storage/folders/move"), "POST", "athena", input, options, runtimeOptions);
2728
4059
  }
2729
4060
  };
2730
- return db;
2731
4061
  }
2732
4062
 
2733
4063
  // src/query-ast.ts
@@ -2757,7 +4087,7 @@ var BOOLEAN_SAFE_OPERATORS = /* @__PURE__ */ new Set([
2757
4087
  "ilike",
2758
4088
  "is"
2759
4089
  ]);
2760
- function isRecord5(value) {
4090
+ function isRecord6(value) {
2761
4091
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
2762
4092
  }
2763
4093
  function isUuidString(value) {
@@ -2770,7 +4100,7 @@ function shouldUseUuidTextComparison(column, value) {
2770
4100
  return typeof value === "string" && isUuidString(value) && isUuidIdentifierColumn(column);
2771
4101
  }
2772
4102
  function isRelationSelectNode(value) {
2773
- return isRecord5(value) && isRecord5(value.select);
4103
+ return isRecord6(value) && isRecord6(value.select);
2774
4104
  }
2775
4105
  function normalizeIdentifier(value, label) {
2776
4106
  const normalized = value.trim();
@@ -2826,7 +4156,7 @@ function compileRelationToken(key, node) {
2826
4156
  return `${prefix}${relationToken}(${nested})`;
2827
4157
  }
2828
4158
  function compileSelectShape(select) {
2829
- if (!isRecord5(select)) {
4159
+ if (!isRecord6(select)) {
2830
4160
  throw new Error("findMany select must be an object");
2831
4161
  }
2832
4162
  const tokens = [];
@@ -2850,7 +4180,7 @@ function compileSelectShape(select) {
2850
4180
  return tokens.join(",");
2851
4181
  }
2852
4182
  function selectShapeUsesRelationSchema(select) {
2853
- if (!isRecord5(select)) {
4183
+ if (!isRecord6(select)) {
2854
4184
  return false;
2855
4185
  }
2856
4186
  for (const rawValue of Object.values(select)) {
@@ -2868,7 +4198,7 @@ function selectShapeUsesRelationSchema(select) {
2868
4198
  }
2869
4199
  function compileColumnWhere(column, input) {
2870
4200
  const normalizedColumn = normalizeIdentifier(column, "where column");
2871
- if (!isRecord5(input)) {
4201
+ if (!isRecord6(input)) {
2872
4202
  return [buildGatewayCondition("eq", normalizedColumn, input)];
2873
4203
  }
2874
4204
  const conditions = [];
@@ -2896,7 +4226,7 @@ function compileColumnWhere(column, input) {
2896
4226
  return conditions;
2897
4227
  }
2898
4228
  function compileBooleanExpressionTerms(clause, label) {
2899
- if (!isRecord5(clause)) {
4229
+ if (!isRecord6(clause)) {
2900
4230
  throw new Error(`findMany where.${label} clauses must be objects`);
2901
4231
  }
2902
4232
  const entries = Object.entries(clause).filter(([, value]) => value !== void 0);
@@ -2905,7 +4235,7 @@ function compileBooleanExpressionTerms(clause, label) {
2905
4235
  }
2906
4236
  const [rawColumn, rawValue] = entries[0];
2907
4237
  const column = normalizeIdentifier(rawColumn, `where.${label} column`);
2908
- if (!isRecord5(rawValue)) {
4238
+ if (!isRecord6(rawValue)) {
2909
4239
  return [`${column}.eq.${stringifyFilterValue(rawValue)}`];
2910
4240
  }
2911
4241
  const operatorEntries = Object.entries(rawValue).filter(([, value]) => value !== void 0);
@@ -2929,7 +4259,7 @@ function compileWhere(where) {
2929
4259
  if (where === void 0) {
2930
4260
  return void 0;
2931
4261
  }
2932
- if (!isRecord5(where)) {
4262
+ if (!isRecord6(where)) {
2933
4263
  throw new Error("findMany where must be an object");
2934
4264
  }
2935
4265
  const conditions = [];
@@ -2979,7 +4309,7 @@ function compileOrderBy(orderBy) {
2979
4309
  if (orderBy === void 0) {
2980
4310
  return void 0;
2981
4311
  }
2982
- if (!isRecord5(orderBy)) {
4312
+ if (!isRecord6(orderBy)) {
2983
4313
  throw new Error("findMany orderBy must be an object");
2984
4314
  }
2985
4315
  if ("column" in orderBy) {
@@ -3154,11 +4484,11 @@ function toFindManyAstOrder(order) {
3154
4484
  ascending: order.direction !== "descending"
3155
4485
  };
3156
4486
  }
3157
- function isRecord6(value) {
4487
+ function isRecord7(value) {
3158
4488
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
3159
4489
  }
3160
4490
  function normalizeFindManyAstColumnPredicate(value) {
3161
- if (!isRecord6(value)) {
4491
+ if (!isRecord7(value)) {
3162
4492
  return {
3163
4493
  eq: value
3164
4494
  };
@@ -3182,7 +4512,7 @@ function normalizeFindManyAstBooleanOperand(clause) {
3182
4512
  return normalized;
3183
4513
  }
3184
4514
  function normalizeFindManyAstWhere(where) {
3185
- if (!where || !isRecord6(where)) {
4515
+ if (!where || !isRecord7(where)) {
3186
4516
  return where;
3187
4517
  }
3188
4518
  const normalized = {};
@@ -3196,7 +4526,7 @@ function normalizeFindManyAstWhere(where) {
3196
4526
  );
3197
4527
  continue;
3198
4528
  }
3199
- if (key === "not" && isRecord6(value)) {
4529
+ if (key === "not" && isRecord7(value)) {
3200
4530
  normalized.not = normalizeFindManyAstBooleanOperand(
3201
4531
  value
3202
4532
  );
@@ -3207,7 +4537,7 @@ function normalizeFindManyAstWhere(where) {
3207
4537
  return normalized;
3208
4538
  }
3209
4539
  function predicateRequiresUuidQueryFallback(column, value) {
3210
- if (!isRecord6(value)) {
4540
+ if (!isRecord7(value)) {
3211
4541
  return shouldUseUuidTextComparison(column, value);
3212
4542
  }
3213
4543
  const eqValue = value.eq;
@@ -3225,7 +4555,7 @@ function booleanOperandRequiresUuidQueryFallback(clause) {
3225
4555
  return false;
3226
4556
  }
3227
4557
  function findManyAstWhereRequiresLegacyTransport(where) {
3228
- if (!where || !isRecord6(where)) {
4558
+ if (!where || !isRecord7(where)) {
3229
4559
  return false;
3230
4560
  }
3231
4561
  for (const [key, value] of Object.entries(where)) {
@@ -3240,7 +4570,7 @@ function findManyAstWhereRequiresLegacyTransport(where) {
3240
4570
  }
3241
4571
  continue;
3242
4572
  }
3243
- if (key === "not" && isRecord6(value)) {
4573
+ if (key === "not" && isRecord7(value)) {
3244
4574
  if (booleanOperandRequiresUuidQueryFallback(value)) {
3245
4575
  return true;
3246
4576
  }
@@ -3442,7 +4772,7 @@ async function executeExperimentalRead(experimental, runner) {
3442
4772
  throw error;
3443
4773
  }
3444
4774
  }
3445
- function isRecord7(value) {
4775
+ function isRecord8(value) {
3446
4776
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
3447
4777
  }
3448
4778
  function firstNonEmptyString2(...values) {
@@ -3454,8 +4784,8 @@ function firstNonEmptyString2(...values) {
3454
4784
  return void 0;
3455
4785
  }
3456
4786
  function resolveStructuredErrorPayload2(raw) {
3457
- if (!isRecord7(raw)) return null;
3458
- return isRecord7(raw.error) ? raw.error : raw;
4787
+ if (!isRecord8(raw)) return null;
4788
+ return isRecord8(raw.error) ? raw.error : raw;
3459
4789
  }
3460
4790
  function resolveStructuredErrorDetails(payload, message) {
3461
4791
  if (!payload || !("details" in payload)) {
@@ -3471,7 +4801,7 @@ function resolveStructuredErrorDetails(payload, message) {
3471
4801
  return details;
3472
4802
  }
3473
4803
  function createResultError(response, result, normalized) {
3474
- const rawRecord = isRecord7(response.raw) ? response.raw : null;
4804
+ const rawRecord = isRecord8(response.raw) ? response.raw : null;
3475
4805
  const payload = resolveStructuredErrorPayload2(response.raw);
3476
4806
  const message = firstNonEmptyString2(
3477
4807
  response.error,
@@ -4934,7 +6264,7 @@ function createClientFromConfig(config) {
4934
6264
  };
4935
6265
  const query = createQueryBuilder(gateway, formatGatewayResult, config.experimental, queryTracer);
4936
6266
  const db = createDbModule({ from, rpc, query });
4937
- return {
6267
+ const sdkClient = {
4938
6268
  from,
4939
6269
  db,
4940
6270
  rpc,
@@ -4942,6 +6272,14 @@ function createClientFromConfig(config) {
4942
6272
  verifyConnection: gateway.verifyConnection,
4943
6273
  auth: auth.auth
4944
6274
  };
6275
+ if (config.experimental?.athenaStorageBackend) {
6276
+ const storageClient = {
6277
+ ...sdkClient,
6278
+ storage: createStorageModule(gateway, config.experimental.storage)
6279
+ };
6280
+ return storageClient;
6281
+ }
6282
+ return sdkClient;
4945
6283
  }
4946
6284
  var DEFAULT_BACKEND = { type: "athena" };
4947
6285
  function toBackendConfig(b) {
@@ -4972,6 +6310,12 @@ function mergeExperimentalOptions(current, next) {
4972
6310
  ...next.traceQueries
4973
6311
  };
4974
6312
  }
6313
+ if (current?.storage || next.storage) {
6314
+ merged.storage = {
6315
+ ...current?.storage ?? {},
6316
+ ...next.storage ?? {}
6317
+ };
6318
+ }
4975
6319
  return merged;
4976
6320
  }
4977
6321
  var AthenaClientBuilderImpl = class {
@@ -5008,7 +6352,7 @@ var AthenaClientBuilderImpl = class {
5008
6352
  }
5009
6353
  experimental(options) {
5010
6354
  this.experimentalOptions = mergeExperimentalOptions(this.experimentalOptions, options);
5011
- return this;
6355
+ return options.athenaStorageBackend ? this : this;
5012
6356
  }
5013
6357
  options(options) {
5014
6358
  if (options.client !== void 0) {
@@ -5029,7 +6373,7 @@ var AthenaClientBuilderImpl = class {
5029
6373
  if (options.experimental !== void 0) {
5030
6374
  this.experimentalOptions = mergeExperimentalOptions(this.experimentalOptions, options.experimental);
5031
6375
  }
5032
- return this;
6376
+ return options.experimental?.athenaStorageBackend ? this : this;
5033
6377
  }
5034
6378
  build() {
5035
6379
  if (!this.baseUrl || !this.apiKey) {
@@ -5225,7 +6569,7 @@ function resolveNullishValue(mode) {
5225
6569
  if (mode === "null") return null;
5226
6570
  return "";
5227
6571
  }
5228
- function isRecord8(value) {
6572
+ function isRecord9(value) {
5229
6573
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
5230
6574
  }
5231
6575
  function isNullableColumn(model, key) {
@@ -5234,7 +6578,7 @@ function isNullableColumn(model, key) {
5234
6578
  }
5235
6579
  function toModelFormDefaults(model, values, options) {
5236
6580
  const source = values;
5237
- if (!isRecord8(source)) {
6581
+ if (!isRecord9(source)) {
5238
6582
  return {};
5239
6583
  }
5240
6584
  const mode = options?.nullishMode ?? "empty-string";
@@ -5309,6 +6653,90 @@ function resolveProviderSchemas(providerConfig) {
5309
6653
  return [...DEFAULT_POSTGRES_SCHEMAS];
5310
6654
  }
5311
6655
 
6656
+ // src/generator/env.ts
6657
+ function readEnvStringValue(key) {
6658
+ if (typeof process === "undefined" || !process.env) {
6659
+ return void 0;
6660
+ }
6661
+ const value = process.env[key];
6662
+ if (typeof value !== "string") {
6663
+ return void 0;
6664
+ }
6665
+ const trimmed = value.trim();
6666
+ return trimmed.length > 0 ? trimmed : void 0;
6667
+ }
6668
+ function throwMissingEnvVar(key) {
6669
+ throw new Error(
6670
+ `Generator config env var ${key} is missing or empty. Set ${key} or provide a default value.`
6671
+ );
6672
+ }
6673
+ function resolveEnvValue(key, options, resolver) {
6674
+ const rawValue = readEnvStringValue(key);
6675
+ if (rawValue === void 0) {
6676
+ if (options?.default !== void 0) {
6677
+ return options.default;
6678
+ }
6679
+ if (options?.optional) {
6680
+ return void 0;
6681
+ }
6682
+ return throwMissingEnvVar(key);
6683
+ }
6684
+ return resolver(rawValue);
6685
+ }
6686
+ function resolveStringEnv(key, options) {
6687
+ return resolveEnvValue(key, options, (value) => value);
6688
+ }
6689
+ function resolveBooleanEnv(key, options) {
6690
+ return resolveEnvValue(key, options, (value) => parseBooleanFlag2(value, false));
6691
+ }
6692
+ function resolveListEnv(key, options) {
6693
+ return resolveEnvValue(key, options, (value) => {
6694
+ const separator = options?.separator ?? ",";
6695
+ return value.split(separator).map((entry) => entry.trim()).filter((entry, index, entries) => entry.length > 0 && entries.indexOf(entry) === index);
6696
+ })?.slice();
6697
+ }
6698
+ function resolveJsonEnv(key, options) {
6699
+ return resolveEnvValue(key, options, (value) => {
6700
+ try {
6701
+ return JSON.parse(value);
6702
+ } catch (error) {
6703
+ const message = error instanceof Error ? error.message : String(error);
6704
+ throw new Error(`Generator config env var ${key} must contain valid JSON. ${message}`);
6705
+ }
6706
+ });
6707
+ }
6708
+ function resolveOneOfEnv(key, allowedValues, options) {
6709
+ return resolveEnvValue(key, options, (value) => {
6710
+ if (allowedValues.includes(value)) {
6711
+ return value;
6712
+ }
6713
+ throw new Error(
6714
+ `Generator config env var ${key} must be one of: ${allowedValues.join(", ")}. Received: ${value}.`
6715
+ );
6716
+ });
6717
+ }
6718
+ function generatorEnvString(key, options) {
6719
+ return resolveStringEnv(key, options);
6720
+ }
6721
+ function generatorEnvBoolean(key, options) {
6722
+ return resolveBooleanEnv(key, options);
6723
+ }
6724
+ function generatorEnvList(key, options) {
6725
+ return resolveListEnv(key, options);
6726
+ }
6727
+ function generatorEnvJson(key, options) {
6728
+ return resolveJsonEnv(key, options);
6729
+ }
6730
+ function generatorEnvOneOf(key, allowedValues, options) {
6731
+ return resolveOneOfEnv(key, allowedValues, options);
6732
+ }
6733
+ var generatorEnv = Object.assign(generatorEnvString, {
6734
+ boolean: generatorEnvBoolean,
6735
+ list: generatorEnvList,
6736
+ json: generatorEnvJson,
6737
+ oneOf: generatorEnvOneOf
6738
+ });
6739
+
5312
6740
  // src/generator/postgres-type-mapping.ts
5313
6741
  var NUMBER_TYPES = /* @__PURE__ */ new Set([
5314
6742
  "int2",
@@ -5425,6 +6853,433 @@ function resolvePostgresColumnType(column) {
5425
6853
  return wrapArrayType(baseType, column.arrayDimensions);
5426
6854
  }
5427
6855
 
6856
+ // src/auth/server.ts
6857
+ var DEFAULT_AUTH_BASE_PATH = "/api/auth";
6858
+ var ATHENA_AUTH_BASE_ERROR_CODES = {
6859
+ HANDLER_NOT_CONFIGURED: "HANDLER_NOT_CONFIGURED",
6860
+ INVALID_BASE_URL: "INVALID_BASE_URL",
6861
+ UNTRUSTED_HOST: "UNTRUSTED_HOST"
6862
+ };
6863
+ function capitalize(value) {
6864
+ return value.length > 0 ? `${value[0]?.toUpperCase()}${value.slice(1)}` : value;
6865
+ }
6866
+ function serializeSetCookieValue(name, value, attributes) {
6867
+ const parts = [`${name}=${encodeURIComponent(value)}`];
6868
+ const knownKeys = /* @__PURE__ */ new Set([
6869
+ "maxAge",
6870
+ "expires",
6871
+ "domain",
6872
+ "path",
6873
+ "secure",
6874
+ "httpOnly",
6875
+ "partitioned",
6876
+ "sameSite"
6877
+ ]);
6878
+ if (attributes.maxAge !== void 0) {
6879
+ parts.push(`Max-Age=${Math.trunc(attributes.maxAge)}`);
6880
+ }
6881
+ if (attributes.expires instanceof Date) {
6882
+ parts.push(`Expires=${attributes.expires.toUTCString()}`);
6883
+ }
6884
+ if (attributes.domain) {
6885
+ parts.push(`Domain=${attributes.domain}`);
6886
+ }
6887
+ if (attributes.path) {
6888
+ parts.push(`Path=${attributes.path}`);
6889
+ }
6890
+ if (attributes.secure) {
6891
+ parts.push("Secure");
6892
+ }
6893
+ if (attributes.httpOnly) {
6894
+ parts.push("HttpOnly");
6895
+ }
6896
+ if (attributes.partitioned) {
6897
+ parts.push("Partitioned");
6898
+ }
6899
+ if (attributes.sameSite) {
6900
+ parts.push(`SameSite=${capitalize(attributes.sameSite)}`);
6901
+ }
6902
+ for (const [key, rawValue] of Object.entries(attributes)) {
6903
+ if (knownKeys.has(key) || rawValue === void 0 || rawValue === null || rawValue === false) {
6904
+ continue;
6905
+ }
6906
+ if (rawValue === true) {
6907
+ parts.push(key);
6908
+ continue;
6909
+ }
6910
+ parts.push(`${key}=${String(rawValue)}`);
6911
+ }
6912
+ return parts.join("; ");
6913
+ }
6914
+ function readCookieFromHeaders(headers, name) {
6915
+ const cookieHeader = headers?.get("cookie");
6916
+ if (!cookieHeader) {
6917
+ return void 0;
6918
+ }
6919
+ return parseCookies(cookieHeader).get(name);
6920
+ }
6921
+ function isRecord10(value) {
6922
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
6923
+ }
6924
+ function resolveSessionCandidate(value) {
6925
+ if (!isRecord10(value)) {
6926
+ return null;
6927
+ }
6928
+ const session = isRecord10(value.session) ? value.session : void 0;
6929
+ const user = isRecord10(value.user) ? value.user : void 0;
6930
+ if (session && typeof session.token === "string" && session.token.length > 0 && user) {
6931
+ return {
6932
+ session,
6933
+ user
6934
+ };
6935
+ }
6936
+ return null;
6937
+ }
6938
+ function inferSessionPair(returned) {
6939
+ return resolveSessionCandidate(returned) ?? (isRecord10(returned) ? resolveSessionCandidate(returned.data) : null) ?? (isRecord10(returned) ? resolveSessionCandidate(returned.session) : null);
6940
+ }
6941
+ function resolveResponseHeaders(ctx) {
6942
+ if (ctx.context.responseHeaders instanceof Headers) {
6943
+ return ctx.context.responseHeaders;
6944
+ }
6945
+ const headers = new Headers();
6946
+ ctx.context.responseHeaders = headers;
6947
+ return headers;
6948
+ }
6949
+ function normalizeBaseURL(baseURL) {
6950
+ return baseURL.replace(/\/$/, "");
6951
+ }
6952
+ function normalizeBasePath(basePath) {
6953
+ if (!basePath || basePath === "/") {
6954
+ return DEFAULT_AUTH_BASE_PATH;
6955
+ }
6956
+ const normalized = basePath.startsWith("/") ? basePath : `/${basePath}`;
6957
+ return normalized.endsWith("/") && normalized.length > 1 ? normalized.slice(0, -1) : normalized;
6958
+ }
6959
+ function isDynamicBaseURLConfig2(baseURL) {
6960
+ return typeof baseURL === "object" && baseURL !== null && "allowedHosts" in baseURL && Array.isArray(baseURL.allowedHosts);
6961
+ }
6962
+ function getRequestUrl(request) {
6963
+ try {
6964
+ return new URL(request.url);
6965
+ } catch {
6966
+ return new URL("http://localhost");
6967
+ }
6968
+ }
6969
+ function getRequestHost(request, url) {
6970
+ const forwardedHost = request.headers.get("x-forwarded-host")?.split(",")[0]?.trim();
6971
+ const host = forwardedHost || request.headers.get("host") || url.host;
6972
+ return host || null;
6973
+ }
6974
+ function getRequestProtocol(request, configuredProtocol, url) {
6975
+ if (configuredProtocol === "http" || configuredProtocol === "https") {
6976
+ return configuredProtocol;
6977
+ }
6978
+ const forwardedProto = request.headers.get("x-forwarded-proto")?.split(",")[0]?.trim();
6979
+ if (forwardedProto === "http" || forwardedProto === "https") {
6980
+ return forwardedProto;
6981
+ }
6982
+ if (url.protocol === "http:" || url.protocol === "https:") {
6983
+ return url.protocol.slice(0, -1);
6984
+ }
6985
+ return "http";
6986
+ }
6987
+ function resolveRequestBaseURL(baseURL, request) {
6988
+ if (typeof baseURL === "string") {
6989
+ return normalizeBaseURL(baseURL);
6990
+ }
6991
+ const requestUrl = getRequestUrl(request);
6992
+ const host = getRequestHost(request, requestUrl);
6993
+ if (!host) {
6994
+ return null;
6995
+ }
6996
+ if (isDynamicBaseURLConfig2(baseURL)) {
6997
+ const allowedHosts = baseURL.allowedHosts ?? [];
6998
+ if (allowedHosts.length > 0 && !allowedHosts.includes(host)) {
6999
+ return null;
7000
+ }
7001
+ }
7002
+ const protocol = typeof baseURL === "object" && baseURL !== null ? getRequestProtocol(request, baseURL.protocol, requestUrl) : getRequestProtocol(request, void 0, requestUrl);
7003
+ return `${protocol}://${host}`;
7004
+ }
7005
+ function getOrigin(baseURL) {
7006
+ if (!baseURL) {
7007
+ return void 0;
7008
+ }
7009
+ try {
7010
+ return new URL(baseURL).origin;
7011
+ } catch {
7012
+ return void 0;
7013
+ }
7014
+ }
7015
+ async function resolveTrustedOrigins(config, baseURL, request) {
7016
+ const resolved = typeof config.trustedOrigins === "function" ? await config.trustedOrigins(request) : config.trustedOrigins ?? [];
7017
+ const values = [
7018
+ getOrigin(baseURL),
7019
+ ...resolved
7020
+ ];
7021
+ return Array.from(new Set(values.filter((value) => typeof value === "string" && value.length > 0)));
7022
+ }
7023
+ async function resolveTrustedProviders(config, request) {
7024
+ const configured = typeof config.trustedProviders === "function" ? await config.trustedProviders(request) : config.trustedProviders ?? [];
7025
+ const values = [
7026
+ ...Object.keys(config.socialProviders ?? {}),
7027
+ ...configured
7028
+ ];
7029
+ return Array.from(new Set(values.filter((value) => typeof value === "string" && value.length > 0)));
7030
+ }
7031
+ function createJsonResponse(payload, init) {
7032
+ const headers = new Headers(init?.headers);
7033
+ if (!headers.has("content-type")) {
7034
+ headers.set("content-type", "application/json; charset=utf-8");
7035
+ }
7036
+ return new Response(JSON.stringify(payload), {
7037
+ ...init,
7038
+ headers
7039
+ });
7040
+ }
7041
+ function mergeResponseHeaders(response, headers) {
7042
+ return new Response(response.body, {
7043
+ status: response.status,
7044
+ statusText: response.statusText,
7045
+ headers
7046
+ });
7047
+ }
7048
+ function defineAthenaAuthConfig(config) {
7049
+ return config;
7050
+ }
7051
+ function athenaAuth(config) {
7052
+ const normalizedBasePath = normalizeBasePath(config.basePath);
7053
+ const staticBaseURL = typeof config.baseURL === "string" ? normalizeBaseURL(config.baseURL) : void 0;
7054
+ const runtime = {
7055
+ baseURL: staticBaseURL,
7056
+ basePath: normalizedBasePath,
7057
+ secret: config.secret,
7058
+ cookies: {
7059
+ session: config.session,
7060
+ advanced: config.advanced
7061
+ }
7062
+ };
7063
+ const resolvedDatabase = typeof config.database === "function" ? config.database(runtime) : config.database;
7064
+ const cookies = getCookies({
7065
+ baseURL: staticBaseURL ?? config.baseURL,
7066
+ session: config.session,
7067
+ advanced: config.advanced
7068
+ });
7069
+ const auth = {};
7070
+ const createCookieContext = (input = {}) => {
7071
+ const responseHeaders = input.responseHeaders ?? new Headers();
7072
+ const runtimeHeaders = input.headers;
7073
+ const authCookies = input.cookies ?? auth.cookies;
7074
+ const setCookie = input.setCookie ?? ((name, value, attributes) => {
7075
+ responseHeaders.append(
7076
+ "set-cookie",
7077
+ serializeSetCookieValue(name, value, attributes)
7078
+ );
7079
+ });
7080
+ return {
7081
+ headers: runtimeHeaders,
7082
+ getCookie: input.getCookie ?? ((name) => readCookieFromHeaders(runtimeHeaders, name)),
7083
+ setCookie,
7084
+ logger: input.logger,
7085
+ setSignedCookie: input.setSignedCookie,
7086
+ getSignedCookie: input.getSignedCookie,
7087
+ context: {
7088
+ secret: runtime.secret,
7089
+ authCookies,
7090
+ sessionConfig: {
7091
+ expiresIn: config.session?.expiresIn
7092
+ },
7093
+ options: {
7094
+ session: {
7095
+ cookieCache: config.session?.cookieCache
7096
+ },
7097
+ account: {
7098
+ storeAccountCookie: true
7099
+ }
7100
+ },
7101
+ setNewSession: input.setNewSession
7102
+ }
7103
+ };
7104
+ };
7105
+ const setSession = async (input, session, dontRememberMe, overrides) => {
7106
+ const cookieContext = createCookieContext(input);
7107
+ await setSessionCookie(cookieContext, session, dontRememberMe, overrides);
7108
+ };
7109
+ const clearSession = (input, skipDontRememberMe) => {
7110
+ const cookieContext = createCookieContext(input);
7111
+ deleteSessionCookie(cookieContext, skipDontRememberMe);
7112
+ };
7113
+ const applyResponseCookies = async (ctx) => {
7114
+ const responseHeaders = resolveResponseHeaders(ctx);
7115
+ const session = ctx.context.setSession ?? inferSessionPair(ctx.context.returned);
7116
+ if (ctx.context.clearSession) {
7117
+ clearSession({
7118
+ headers: ctx.headers,
7119
+ responseHeaders
7120
+ });
7121
+ }
7122
+ if (session) {
7123
+ await setSession(
7124
+ {
7125
+ headers: ctx.headers,
7126
+ responseHeaders
7127
+ },
7128
+ session,
7129
+ ctx.context.dontRememberMe,
7130
+ ctx.context.cookieOverrides
7131
+ );
7132
+ }
7133
+ return responseHeaders;
7134
+ };
7135
+ const runAfterHooks = async (ctx) => {
7136
+ for (const plugin of auth.plugins) {
7137
+ for (const hook of plugin.hooks?.after ?? []) {
7138
+ if (!hook.matcher(ctx)) {
7139
+ continue;
7140
+ }
7141
+ await hook.handler({
7142
+ ...ctx,
7143
+ auth
7144
+ });
7145
+ }
7146
+ }
7147
+ return ctx;
7148
+ };
7149
+ const resolveRequestContext = async (request) => {
7150
+ const requestUrl = getRequestUrl(request);
7151
+ const resolvedBaseURL = resolveRequestBaseURL(config.baseURL, request);
7152
+ if (!resolvedBaseURL) {
7153
+ throw new Error(
7154
+ isDynamicBaseURLConfig2(config.baseURL) ? "Could not resolve base URL from request. Check allowedHosts/baseURL." : "Could not resolve base URL from request."
7155
+ );
7156
+ }
7157
+ const requestCookies = getCookies({
7158
+ baseURL: resolvedBaseURL,
7159
+ session: config.session,
7160
+ advanced: config.advanced
7161
+ });
7162
+ const trustedOrigins = await resolveTrustedOrigins(config, resolvedBaseURL, request);
7163
+ const trustedProviders = await resolveTrustedProviders(config, request);
7164
+ return {
7165
+ auth,
7166
+ request,
7167
+ url: requestUrl,
7168
+ path: requestUrl.pathname,
7169
+ basePath: normalizedBasePath,
7170
+ baseURL: resolvedBaseURL,
7171
+ origin: getOrigin(resolvedBaseURL) ?? resolvedBaseURL,
7172
+ headers: request.headers,
7173
+ cookies: requestCookies,
7174
+ trustedOrigins,
7175
+ trustedProviders,
7176
+ options: config,
7177
+ runtime: {
7178
+ ...runtime,
7179
+ baseURL: resolvedBaseURL
7180
+ },
7181
+ database: auth.database,
7182
+ socialProviders: auth.socialProviders
7183
+ };
7184
+ };
7185
+ const handler = async (request) => {
7186
+ const requestContext = await resolveRequestContext(request);
7187
+ if (typeof config.handler !== "function") {
7188
+ return createJsonResponse(
7189
+ {
7190
+ ok: false,
7191
+ code: ATHENA_AUTH_BASE_ERROR_CODES.HANDLER_NOT_CONFIGURED,
7192
+ error: "No native auth handler was configured for this Athena auth instance.",
7193
+ path: requestContext.path,
7194
+ basePath: requestContext.basePath
7195
+ },
7196
+ { status: 501 }
7197
+ );
7198
+ }
7199
+ const result = await config.handler(requestContext);
7200
+ if (result instanceof Response) {
7201
+ return result;
7202
+ }
7203
+ const response = result.response ?? (result.returned !== void 0 ? createJsonResponse(result.returned) : new Response(null, { status: 204 }));
7204
+ const responseHeaders = new Headers(response.headers);
7205
+ await runAfterHooks({
7206
+ path: requestContext.path,
7207
+ headers: request.headers,
7208
+ context: {
7209
+ responseHeaders,
7210
+ returned: result.returned,
7211
+ setSession: result.setSession,
7212
+ clearSession: result.clearSession,
7213
+ dontRememberMe: result.dontRememberMe,
7214
+ cookieOverrides: result.cookieOverrides
7215
+ }
7216
+ });
7217
+ return mergeResponseHeaders(response, responseHeaders);
7218
+ };
7219
+ const api = Object.assign(
7220
+ {
7221
+ applyResponseCookies,
7222
+ clearSession,
7223
+ createCookieContext,
7224
+ getCookieCache,
7225
+ getSessionCookie,
7226
+ resolveRequestContext,
7227
+ runAfterHooks,
7228
+ setSession
7229
+ },
7230
+ config.api ?? {}
7231
+ );
7232
+ const $ERROR_CODES = {
7233
+ ...auth.plugins?.reduce((acc, plugin) => {
7234
+ if (plugin.$ERROR_CODES) {
7235
+ return {
7236
+ ...acc,
7237
+ ...plugin.$ERROR_CODES
7238
+ };
7239
+ }
7240
+ return acc;
7241
+ }, {}),
7242
+ ...config.errorCodes ?? {},
7243
+ ...ATHENA_AUTH_BASE_ERROR_CODES
7244
+ };
7245
+ Object.assign(auth, {
7246
+ config,
7247
+ options: config,
7248
+ runtime,
7249
+ database: resolvedDatabase,
7250
+ socialProviders: config.socialProviders ?? {},
7251
+ plugins: [...config.plugins ?? []],
7252
+ cookies,
7253
+ api,
7254
+ $ERROR_CODES,
7255
+ createCookieContext,
7256
+ setSession,
7257
+ clearSession,
7258
+ applyResponseCookies,
7259
+ runAfterHooks,
7260
+ resolveRequestContext,
7261
+ handler
7262
+ });
7263
+ auth.$context = Promise.all([
7264
+ resolveTrustedOrigins(config, staticBaseURL),
7265
+ resolveTrustedProviders(config)
7266
+ ]).then(([trustedOrigins, trustedProviders]) => ({
7267
+ auth,
7268
+ options: config,
7269
+ runtime,
7270
+ basePath: normalizedBasePath,
7271
+ baseURL: staticBaseURL,
7272
+ origin: getOrigin(staticBaseURL),
7273
+ database: auth.database,
7274
+ socialProviders: auth.socialProviders,
7275
+ plugins: auth.plugins,
7276
+ cookies: auth.cookies,
7277
+ trustedOrigins,
7278
+ trustedProviders
7279
+ }));
7280
+ return auth;
7281
+ }
7282
+
5428
7283
  // src/browser.ts
5429
7284
  function throwBrowserUnsupported(apiName) {
5430
7285
  throw new Error(
@@ -5456,22 +7311,28 @@ async function runSchemaGenerator(options = {}) {
5456
7311
  return throwBrowserUnsupported("runSchemaGenerator");
5457
7312
  }
5458
7313
 
7314
+ exports.ATHENA_AUTH_BASE_ERROR_CODES = ATHENA_AUTH_BASE_ERROR_CODES;
5459
7315
  exports.AthenaClient = AthenaClient;
5460
7316
  exports.AthenaError = AthenaError;
5461
7317
  exports.AthenaErrorCategory = AthenaErrorCategory;
5462
7318
  exports.AthenaErrorCode = AthenaErrorCode;
5463
7319
  exports.AthenaErrorKind = AthenaErrorKind;
5464
7320
  exports.AthenaGatewayError = AthenaGatewayError;
7321
+ exports.AthenaStorageError = AthenaStorageError;
7322
+ exports.AthenaStorageErrorCode = AthenaStorageErrorCode;
5465
7323
  exports.Backend = Backend;
5466
7324
  exports.DEFAULT_POSTGRES_SCHEMAS = DEFAULT_POSTGRES_SCHEMAS;
5467
7325
  exports.assertInt = assertInt;
7326
+ exports.athenaAuth = athenaAuth;
5468
7327
  exports.coerceInt = coerceInt;
7328
+ exports.createAthenaStorageError = createAthenaStorageError;
5469
7329
  exports.createAuthClient = createAuthClient;
5470
7330
  exports.createAuthReactEmailInput = createAuthReactEmailInput;
5471
7331
  exports.createClient = createClient;
5472
7332
  exports.createModelFormAdapter = createModelFormAdapter;
5473
7333
  exports.createPostgresIntrospectionProvider = createPostgresIntrospectionProvider;
5474
7334
  exports.createTypedClient = createTypedClient;
7335
+ exports.defineAthenaAuthConfig = defineAthenaAuthConfig;
5475
7336
  exports.defineAuthEmailTemplate = defineAuthEmailTemplate;
5476
7337
  exports.defineDatabase = defineDatabase;
5477
7338
  exports.defineGeneratorConfig = defineGeneratorConfig;
@@ -5480,6 +7341,7 @@ exports.defineRegistry = defineRegistry;
5480
7341
  exports.defineSchema = defineSchema;
5481
7342
  exports.findGeneratorConfigPath = findGeneratorConfigPath;
5482
7343
  exports.generateArtifactsFromSnapshot = generateArtifactsFromSnapshot;
7344
+ exports.generatorEnv = generatorEnv;
5483
7345
  exports.identifier = identifier;
5484
7346
  exports.isAthenaGatewayError = isAthenaGatewayError;
5485
7347
  exports.isOk = isOk;
@@ -5496,6 +7358,7 @@ exports.resolveGeneratorProvider = resolveGeneratorProvider;
5496
7358
  exports.resolvePostgresColumnType = resolvePostgresColumnType;
5497
7359
  exports.resolveProviderSchemas = resolveProviderSchemas;
5498
7360
  exports.runSchemaGenerator = runSchemaGenerator;
7361
+ exports.storageSdkManifest = storageSdkManifest;
5499
7362
  exports.toModelFormDefaults = toModelFormDefaults;
5500
7363
  exports.toModelPayload = toModelPayload;
5501
7364
  exports.unwrap = unwrap;