@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/index.js CHANGED
@@ -130,6 +130,60 @@ function buildAthenaGatewayUrl(baseUrl, path) {
130
130
  return `${baseUrl}${path}`;
131
131
  }
132
132
 
133
+ // src/cookies/base64.ts
134
+ function getAtob() {
135
+ const candidate = globalThis.atob;
136
+ return typeof candidate === "function" ? candidate : void 0;
137
+ }
138
+ function getBtoa() {
139
+ const candidate = globalThis.btoa;
140
+ return typeof candidate === "function" ? candidate : void 0;
141
+ }
142
+ function bytesToBinaryString(bytes) {
143
+ let result = "";
144
+ for (const byte of bytes) {
145
+ result += String.fromCharCode(byte);
146
+ }
147
+ return result;
148
+ }
149
+ function binaryStringToBytes(binary) {
150
+ const bytes = new Uint8Array(binary.length);
151
+ for (let i = 0; i < binary.length; i++) {
152
+ bytes[i] = binary.charCodeAt(i);
153
+ }
154
+ return bytes;
155
+ }
156
+ function encodeBase64(bytes) {
157
+ const btoaFn = getBtoa();
158
+ if (btoaFn) {
159
+ return btoaFn(bytesToBinaryString(bytes));
160
+ }
161
+ return Buffer.from(bytes).toString("base64");
162
+ }
163
+ function decodeBase64(base64) {
164
+ const atobFn = getAtob();
165
+ if (atobFn) {
166
+ return binaryStringToBytes(atobFn(base64));
167
+ }
168
+ return new Uint8Array(Buffer.from(base64, "base64"));
169
+ }
170
+ function encodeBytesToBase64Url(bytes) {
171
+ return encodeBase64(bytes).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
172
+ }
173
+ function encodeStringToBase64Url(value) {
174
+ const bytes = new TextEncoder().encode(value);
175
+ return encodeBytesToBase64Url(bytes);
176
+ }
177
+ function decodeBase64UrlToBytes(value) {
178
+ const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
179
+ const paddingLength = normalized.length % 4;
180
+ const padded = paddingLength === 0 ? normalized : `${normalized}${"=".repeat(4 - paddingLength)}`;
181
+ return decodeBase64(padded);
182
+ }
183
+ function decodeBase64UrlToString(value) {
184
+ return new TextDecoder().decode(decodeBase64UrlToBytes(value));
185
+ }
186
+
133
187
  // src/cookies/cookie-utils.ts
134
188
  var SECURE_COOKIE_PREFIX = "__Secure-";
135
189
  function parseCookies(cookieHeader) {
@@ -141,12 +195,480 @@ function parseCookies(cookieHeader) {
141
195
  });
142
196
  return cookieMap;
143
197
  }
198
+
199
+ // src/cookies/crypto.ts
200
+ var HS256_ALG = "HS256";
201
+ async function getSubtleCrypto() {
202
+ const globalCrypto = globalThis.crypto;
203
+ if (globalCrypto?.subtle) {
204
+ return globalCrypto.subtle;
205
+ }
206
+ const { webcrypto } = await import('crypto');
207
+ const subtle = webcrypto.subtle;
208
+ if (!subtle) {
209
+ throw new Error("Web Crypto subtle API is unavailable.");
210
+ }
211
+ return subtle;
212
+ }
213
+ async function importHmacKey(secret, usage) {
214
+ const subtle = await getSubtleCrypto();
215
+ return subtle.importKey(
216
+ "raw",
217
+ new TextEncoder().encode(secret),
218
+ {
219
+ name: "HMAC",
220
+ hash: "SHA-256"
221
+ },
222
+ false,
223
+ [usage]
224
+ );
225
+ }
226
+ function bufferToBytes(buffer) {
227
+ return new Uint8Array(buffer);
228
+ }
229
+ function parseJwtPayload(payloadSegment) {
230
+ try {
231
+ const decoded = decodeBase64UrlToString(payloadSegment);
232
+ const payload = JSON.parse(decoded);
233
+ if (!payload || typeof payload !== "object") {
234
+ return null;
235
+ }
236
+ return payload;
237
+ } catch {
238
+ return null;
239
+ }
240
+ }
241
+ function isJwtExpired(payload) {
242
+ const exp = payload.exp;
243
+ if (typeof exp !== "number") {
244
+ return false;
245
+ }
246
+ return exp < Math.floor(Date.now() / 1e3);
247
+ }
248
+ async function signHmacBase64Url(secret, value) {
249
+ const subtle = await getSubtleCrypto();
250
+ const key = await importHmacKey(secret, "sign");
251
+ const signature = await subtle.sign("HMAC", key, new TextEncoder().encode(value));
252
+ return encodeBytesToBase64Url(bufferToBytes(signature));
253
+ }
254
+ async function signJwtHS256(payload, secret, expiresIn = 60 * 5) {
255
+ const now = Math.floor(Date.now() / 1e3);
256
+ const header = { alg: HS256_ALG, typ: "JWT" };
257
+ const fullPayload = {
258
+ ...payload,
259
+ iat: now,
260
+ exp: now + expiresIn
261
+ };
262
+ const headerPart = encodeStringToBase64Url(JSON.stringify(header));
263
+ const payloadPart = encodeStringToBase64Url(JSON.stringify(fullPayload));
264
+ const message = `${headerPart}.${payloadPart}`;
265
+ const signature = await signHmacBase64Url(secret, message);
266
+ return `${message}.${signature}`;
267
+ }
268
+ async function verifyJwtHS256(token, secret) {
269
+ const parts = token.split(".");
270
+ if (parts.length !== 3) {
271
+ return null;
272
+ }
273
+ const [headerPart, payloadPart, signaturePart] = parts;
274
+ if (!headerPart || !payloadPart || !signaturePart) {
275
+ return null;
276
+ }
277
+ let header = null;
278
+ try {
279
+ header = JSON.parse(decodeBase64UrlToString(headerPart));
280
+ } catch {
281
+ return null;
282
+ }
283
+ if (!header || header.alg !== HS256_ALG) {
284
+ return null;
285
+ }
286
+ const payload = parseJwtPayload(payloadPart);
287
+ if (!payload) {
288
+ return null;
289
+ }
290
+ const expectedSignature = await signHmacBase64Url(secret, `${headerPart}.${payloadPart}`);
291
+ if (expectedSignature !== signaturePart) {
292
+ return null;
293
+ }
294
+ if (isJwtExpired(payload)) {
295
+ return null;
296
+ }
297
+ return payload;
298
+ }
299
+
300
+ // src/cookies/session-store.ts
301
+ var ALLOWED_COOKIE_SIZE = 4096;
302
+ var ESTIMATED_EMPTY_COOKIE_SIZE = 200;
303
+ var CHUNK_SIZE = ALLOWED_COOKIE_SIZE - ESTIMATED_EMPTY_COOKIE_SIZE;
304
+ function getChunkIndex(cookieName) {
305
+ const parts = cookieName.split(".");
306
+ const lastPart = parts[parts.length - 1];
307
+ const index = parseInt(lastPart || "0", 10);
308
+ return Number.isNaN(index) ? 0 : index;
309
+ }
310
+ function readExistingChunks(cookieName, ctx) {
311
+ const chunks = {};
312
+ const cookies = parseCookies(ctx.headers?.get("cookie") || "");
313
+ for (const [name, value] of cookies) {
314
+ if (name.startsWith(cookieName)) {
315
+ chunks[name] = value;
316
+ }
317
+ }
318
+ return chunks;
319
+ }
320
+ function joinChunks(chunks) {
321
+ const sortedKeys = Object.keys(chunks).sort((left, right) => getChunkIndex(left) - getChunkIndex(right));
322
+ return sortedKeys.map((key) => chunks[key]).join("");
323
+ }
324
+ function chunkCookie(storeName, cookie, chunks, ctx) {
325
+ const chunkCount = Math.ceil(cookie.value.length / CHUNK_SIZE);
326
+ if (chunkCount === 1) {
327
+ chunks[cookie.name] = cookie.value;
328
+ return [cookie];
329
+ }
330
+ const cookies = [];
331
+ for (let index = 0; index < chunkCount; index++) {
332
+ const name = `${cookie.name}.${index}`;
333
+ const start = index * CHUNK_SIZE;
334
+ const value = cookie.value.substring(start, start + CHUNK_SIZE);
335
+ cookies.push({
336
+ ...cookie,
337
+ name,
338
+ value
339
+ });
340
+ chunks[name] = value;
341
+ }
342
+ ctx.logger?.debug?.(`CHUNKING_${storeName.toUpperCase()}_COOKIE`, {
343
+ message: `${storeName} cookie exceeds allowed ${ALLOWED_COOKIE_SIZE} bytes.`,
344
+ emptyCookieSize: ESTIMATED_EMPTY_COOKIE_SIZE,
345
+ valueSize: cookie.value.length,
346
+ chunkCount,
347
+ chunks: cookies.map((entry) => entry.value.length + ESTIMATED_EMPTY_COOKIE_SIZE)
348
+ });
349
+ return cookies;
350
+ }
351
+ function getCleanCookies(chunks, cookieOptions) {
352
+ const cleanedChunks = {};
353
+ for (const name in chunks) {
354
+ cleanedChunks[name] = {
355
+ name,
356
+ value: "",
357
+ attributes: {
358
+ ...cookieOptions,
359
+ maxAge: 0
360
+ }
361
+ };
362
+ }
363
+ return cleanedChunks;
364
+ }
365
+ var storeFactory = (storeName) => (cookieName, cookieOptions, ctx) => {
366
+ const chunks = readExistingChunks(cookieName, ctx);
367
+ return {
368
+ getValue() {
369
+ return joinChunks(chunks);
370
+ },
371
+ hasChunks() {
372
+ return Object.keys(chunks).length > 0;
373
+ },
374
+ chunk(value, options) {
375
+ const cleanedChunks = getCleanCookies(chunks, cookieOptions);
376
+ for (const name in chunks) {
377
+ delete chunks[name];
378
+ }
379
+ const cookies = cleanedChunks;
380
+ const chunked = chunkCookie(
381
+ storeName,
382
+ {
383
+ name: cookieName,
384
+ value,
385
+ attributes: {
386
+ ...cookieOptions,
387
+ ...options
388
+ }
389
+ },
390
+ chunks,
391
+ ctx
392
+ );
393
+ for (const chunk of chunked) {
394
+ cookies[chunk.name] = chunk;
395
+ }
396
+ return Object.values(cookies);
397
+ },
398
+ clean() {
399
+ const cleanedChunks = getCleanCookies(chunks, cookieOptions);
400
+ for (const name in chunks) {
401
+ delete chunks[name];
402
+ }
403
+ return Object.values(cleanedChunks);
404
+ },
405
+ setCookies(cookies) {
406
+ for (const cookie of cookies) {
407
+ ctx.setCookie(cookie.name, cookie.value, cookie.attributes);
408
+ }
409
+ }
410
+ };
411
+ };
412
+ var createSessionStore = storeFactory("Session");
413
+ var createAccountStore = storeFactory("Account");
414
+
415
+ // src/cookies/index.ts
416
+ var DEFAULT_COOKIE_PREFIX = "athena-auth";
417
+ var LEGACY_COOKIE_PREFIX = "better-auth";
418
+ var DEFAULT_SESSION_MAX_AGE = 7 * 24 * 60 * 60;
419
+ var DEFAULT_CACHE_MAX_AGE = 60 * 5;
420
+ function isProductionRuntime() {
421
+ return typeof process !== "undefined" && process.env?.NODE_ENV === "production";
422
+ }
423
+ function getEnvironmentSecret() {
424
+ if (typeof process === "undefined") {
425
+ return void 0;
426
+ }
427
+ return process.env?.ATHENA_AUTH_SECRET || process.env?.BETTER_AUTH_SECRET || process.env?.AUTH_SECRET;
428
+ }
429
+ function isDynamicBaseURLConfig(baseURL) {
430
+ return typeof baseURL === "object" && baseURL !== null && "allowedHosts" in baseURL && Array.isArray(baseURL.allowedHosts);
431
+ }
432
+ function resolveCookiePrefixes(primaryPrefix) {
433
+ const prefixes = [primaryPrefix];
434
+ if (!prefixes.includes(DEFAULT_COOKIE_PREFIX)) {
435
+ prefixes.push(DEFAULT_COOKIE_PREFIX);
436
+ }
437
+ if (!prefixes.includes(LEGACY_COOKIE_PREFIX)) {
438
+ prefixes.push(LEGACY_COOKIE_PREFIX);
439
+ }
440
+ return prefixes;
441
+ }
442
+ function createError(message) {
443
+ return new Error(`@xylex-group/athena/cookies: ${message}`);
444
+ }
445
+ function getSecretOrThrow(secret) {
446
+ const resolved = secret || getEnvironmentSecret();
447
+ if (!resolved) {
448
+ throw createError(
449
+ "getCookieCache requires a secret. Pass `secret` or set ATHENA_AUTH_SECRET/BETTER_AUTH_SECRET/AUTH_SECRET."
450
+ );
451
+ }
452
+ return resolved;
453
+ }
454
+ function asObject(value) {
455
+ if (!value || typeof value !== "object") {
456
+ return null;
457
+ }
458
+ return value;
459
+ }
460
+ function getSessionTokenFromPair(session) {
461
+ const token = session.session?.token;
462
+ if (typeof token !== "string" || token.length === 0) {
463
+ throw createError("setSessionCookie requires `session.session.token` to be a non-empty string.");
464
+ }
465
+ return token;
466
+ }
467
+ async function resolveCookieVersion(versionConfig, session, user) {
468
+ if (!versionConfig) {
469
+ return "1";
470
+ }
471
+ if (typeof versionConfig === "string") {
472
+ return versionConfig;
473
+ }
474
+ return versionConfig(session, user);
475
+ }
476
+ function getSessionCookieCacheName(cookiePrefix, cookieName, isSecure) {
477
+ return isSecure ? `${SECURE_COOKIE_PREFIX}${cookiePrefix}.${cookieName}` : `${cookiePrefix}.${cookieName}`;
478
+ }
479
+ async function setCookieValue(ctx, name, value, attributes) {
480
+ const secret = ctx.context.secret;
481
+ if (secret && typeof ctx.setSignedCookie === "function") {
482
+ await ctx.setSignedCookie(name, value, secret, attributes);
483
+ return;
484
+ }
485
+ ctx.setCookie(name, value, attributes);
486
+ }
487
+ function parseJsonSafely(value) {
488
+ try {
489
+ return JSON.parse(value);
490
+ } catch {
491
+ return null;
492
+ }
493
+ }
494
+ function getIsSecureCookie(config) {
495
+ if (config?.isSecure !== void 0) {
496
+ return config.isSecure;
497
+ }
498
+ return isProductionRuntime();
499
+ }
500
+ function createCookieGetter(options) {
501
+ const baseURLString = typeof options.baseURL === "string" ? options.baseURL : void 0;
502
+ const dynamicProtocol = typeof options.baseURL === "object" && options.baseURL !== null ? options.baseURL.protocol : void 0;
503
+ const secure = options.advanced?.useSecureCookies !== void 0 ? options.advanced.useSecureCookies : dynamicProtocol === "https" ? true : dynamicProtocol === "http" ? false : baseURLString ? baseURLString.startsWith("https://") : isProductionRuntime();
504
+ const secureCookiePrefix = secure ? SECURE_COOKIE_PREFIX : "";
505
+ const crossSubdomainEnabled = !!options.advanced?.crossSubDomainCookies?.enabled;
506
+ const domain = crossSubdomainEnabled ? options.advanced?.crossSubDomainCookies?.domain || (baseURLString ? new URL(baseURLString).hostname : void 0) : void 0;
507
+ if (crossSubdomainEnabled && !domain && !isDynamicBaseURLConfig(options.baseURL)) {
508
+ throw createError("baseURL is required when `crossSubDomainCookies.enabled` is true.");
509
+ }
510
+ function createCookie(cookieName, overrideAttributes = {}) {
511
+ const prefix = options.advanced?.cookiePrefix || DEFAULT_COOKIE_PREFIX;
512
+ const name = options.advanced?.cookies?.[cookieName]?.name || `${prefix}.${cookieName}`;
513
+ const attributes = options.advanced?.cookies?.[cookieName]?.attributes || {};
514
+ return {
515
+ name: `${secureCookiePrefix}${name}`,
516
+ attributes: {
517
+ secure: !!secureCookiePrefix,
518
+ sameSite: "lax",
519
+ path: "/",
520
+ httpOnly: true,
521
+ ...crossSubdomainEnabled ? { domain } : {},
522
+ ...options.advanced?.defaultCookieAttributes,
523
+ ...overrideAttributes,
524
+ ...attributes
525
+ }
526
+ };
527
+ }
528
+ return createCookie;
529
+ }
530
+ function getCookies(options) {
531
+ const createCookie = createCookieGetter(options);
532
+ const sessionToken = createCookie("session_token", { maxAge: options.session?.expiresIn || DEFAULT_SESSION_MAX_AGE });
533
+ const sessionData = createCookie("session_data", { maxAge: options.session?.cookieCache?.maxAge || DEFAULT_CACHE_MAX_AGE });
534
+ const accountData = createCookie("account_data", { maxAge: options.session?.cookieCache?.maxAge || DEFAULT_CACHE_MAX_AGE });
535
+ const dontRememberToken = createCookie("dont_remember");
536
+ return {
537
+ sessionToken: {
538
+ name: sessionToken.name,
539
+ attributes: sessionToken.attributes
540
+ },
541
+ sessionData: {
542
+ name: sessionData.name,
543
+ attributes: sessionData.attributes
544
+ },
545
+ dontRememberToken: {
546
+ name: dontRememberToken.name,
547
+ attributes: dontRememberToken.attributes
548
+ },
549
+ accountData: {
550
+ name: accountData.name,
551
+ attributes: accountData.attributes
552
+ }
553
+ };
554
+ }
555
+ async function setCookieCache(ctx, session, dontRememberMe) {
556
+ const cookieCacheConfig = ctx.context.options?.session?.cookieCache;
557
+ if (!cookieCacheConfig?.enabled) {
558
+ return;
559
+ }
560
+ const version = await resolveCookieVersion(
561
+ cookieCacheConfig.version,
562
+ session.session,
563
+ session.user
564
+ );
565
+ const sessionData = {
566
+ session: session.session,
567
+ user: session.user,
568
+ updatedAt: Date.now(),
569
+ version
570
+ };
571
+ const baseAttributes = ctx.context.authCookies.sessionData.attributes;
572
+ const maxAge = dontRememberMe ? void 0 : baseAttributes.maxAge;
573
+ const options = {
574
+ ...baseAttributes,
575
+ maxAge
576
+ };
577
+ const expiresAt = Date.now() + (options.maxAge || 60) * 1e3;
578
+ const strategy = cookieCacheConfig.strategy || "compact";
579
+ const secret = getSecretOrThrow(ctx.context.secret);
580
+ let encoded;
581
+ if (strategy === "jwt") {
582
+ encoded = await signJwtHS256(sessionData, secret, options.maxAge || DEFAULT_CACHE_MAX_AGE);
583
+ } else if (strategy === "jwe") {
584
+ throw createError("`jwe` strategy is not supported by the SDK cookie helper.");
585
+ } else {
586
+ const signature = await signHmacBase64Url(
587
+ secret,
588
+ JSON.stringify({
589
+ ...sessionData,
590
+ expiresAt
591
+ })
592
+ );
593
+ encoded = encodeStringToBase64Url(
594
+ JSON.stringify({
595
+ session: sessionData,
596
+ expiresAt,
597
+ signature
598
+ })
599
+ );
600
+ }
601
+ if (encoded.length > 4093) {
602
+ const store = createSessionStore(ctx.context.authCookies.sessionData.name, options, ctx);
603
+ const cookies = store.chunk(encoded, options);
604
+ store.setCookies(cookies);
605
+ } else {
606
+ const store = createSessionStore(ctx.context.authCookies.sessionData.name, options, ctx);
607
+ if (store.hasChunks()) {
608
+ store.setCookies(store.clean());
609
+ }
610
+ ctx.setCookie(ctx.context.authCookies.sessionData.name, encoded, options);
611
+ }
612
+ }
613
+ async function setSessionCookie(ctx, session, dontRememberMe, overrides) {
614
+ if (dontRememberMe === void 0 && typeof ctx.getSignedCookie === "function" && ctx.context.secret) {
615
+ const existingFlag = await ctx.getSignedCookie(ctx.context.authCookies.dontRememberToken.name, ctx.context.secret);
616
+ dontRememberMe = !!existingFlag;
617
+ }
618
+ const resolvedDontRememberMe = dontRememberMe ?? false;
619
+ const token = getSessionTokenFromPair(session);
620
+ const options = ctx.context.authCookies.sessionToken.attributes;
621
+ const maxAge = resolvedDontRememberMe ? void 0 : ctx.context.sessionConfig?.expiresIn;
622
+ await setCookieValue(ctx, ctx.context.authCookies.sessionToken.name, token, {
623
+ ...options,
624
+ maxAge,
625
+ ...overrides
626
+ });
627
+ if (resolvedDontRememberMe) {
628
+ await setCookieValue(
629
+ ctx,
630
+ ctx.context.authCookies.dontRememberToken.name,
631
+ "true",
632
+ ctx.context.authCookies.dontRememberToken.attributes
633
+ );
634
+ }
635
+ await setCookieCache(ctx, session, resolvedDontRememberMe);
636
+ ctx.context.setNewSession?.(session);
637
+ }
638
+ function expireCookie(ctx, cookie) {
639
+ ctx.setCookie(cookie.name, "", {
640
+ ...cookie.attributes,
641
+ maxAge: 0
642
+ });
643
+ }
644
+ function deleteSessionCookie(ctx, skipDontRememberMe) {
645
+ expireCookie(ctx, ctx.context.authCookies.sessionToken);
646
+ expireCookie(ctx, ctx.context.authCookies.sessionData);
647
+ if (ctx.context.options?.account?.storeAccountCookie) {
648
+ expireCookie(ctx, ctx.context.authCookies.accountData);
649
+ const accountStore = createAccountStore(
650
+ ctx.context.authCookies.accountData.name,
651
+ ctx.context.authCookies.accountData.attributes,
652
+ ctx
653
+ );
654
+ accountStore.setCookies(accountStore.clean());
655
+ }
656
+ const sessionStore = createSessionStore(
657
+ ctx.context.authCookies.sessionData.name,
658
+ ctx.context.authCookies.sessionData.attributes,
659
+ ctx
660
+ );
661
+ sessionStore.setCookies(sessionStore.clean());
662
+ if (!skipDontRememberMe) {
663
+ expireCookie(ctx, ctx.context.authCookies.dontRememberToken);
664
+ }
665
+ }
144
666
  var getSessionCookie = (request, config) => {
145
667
  const cookies = (request instanceof Headers || !("headers" in request) ? request : request.headers).get("cookie");
146
668
  if (!cookies) {
147
669
  return null;
148
670
  }
149
- const { cookieName = "session_token", cookiePrefix = "athena-auth" } = {};
671
+ const { cookieName = "session_token", cookiePrefix = "athena-auth" } = config || {};
150
672
  const parsedCookie = parseCookies(cookies);
151
673
  const getCookie = (name) => parsedCookie.get(name) || parsedCookie.get(`${SECURE_COOKIE_PREFIX}${name}`);
152
674
  const sessionToken = getCookie(`${cookiePrefix}.${cookieName}`) || getCookie(`${cookiePrefix}-${cookieName}`);
@@ -155,10 +677,126 @@ var getSessionCookie = (request, config) => {
155
677
  }
156
678
  return null;
157
679
  };
680
+ var getCookieCache = async (request, config) => {
681
+ const headers = request instanceof Headers || !("headers" in request) ? request : request.headers;
682
+ const cookieHeader = headers.get("cookie");
683
+ if (!cookieHeader) {
684
+ return null;
685
+ }
686
+ const parsedCookie = parseCookies(cookieHeader);
687
+ const cookieName = config?.cookieName || "session_data";
688
+ const requestedPrefix = config?.cookiePrefix || DEFAULT_COOKIE_PREFIX;
689
+ const strategy = config?.strategy || "compact";
690
+ const cookiePrefixes = resolveCookiePrefixes(requestedPrefix);
691
+ const isSecure = getIsSecureCookie(config);
692
+ const secret = getSecretOrThrow(config?.secret);
693
+ let sessionData;
694
+ for (const prefix of cookiePrefixes) {
695
+ const candidate = getSessionCookieCacheName(prefix, cookieName, isSecure);
696
+ const cookieValue = parsedCookie.get(candidate);
697
+ if (cookieValue) {
698
+ sessionData = cookieValue;
699
+ break;
700
+ }
701
+ }
702
+ if (!sessionData) {
703
+ const reconstructedChunks = [];
704
+ for (const prefix of cookiePrefixes) {
705
+ const candidate = getSessionCookieCacheName(prefix, cookieName, isSecure);
706
+ for (const [name, value] of parsedCookie.entries()) {
707
+ if (!name.startsWith(`${candidate}.`)) {
708
+ continue;
709
+ }
710
+ const parts = name.split(".");
711
+ const indexStr = parts[parts.length - 1];
712
+ const index = parseInt(indexStr || "0", 10);
713
+ if (!Number.isNaN(index)) {
714
+ reconstructedChunks.push({ index, value });
715
+ }
716
+ }
717
+ if (reconstructedChunks.length > 0) {
718
+ break;
719
+ }
720
+ }
721
+ if (reconstructedChunks.length > 0) {
722
+ reconstructedChunks.sort((left, right) => left.index - right.index);
723
+ sessionData = reconstructedChunks.map((chunk) => chunk.value).join("");
724
+ }
725
+ }
726
+ if (!sessionData) {
727
+ return null;
728
+ }
729
+ if (strategy === "jwe") {
730
+ throw createError(
731
+ "`jwe` strategy is not supported by the SDK cookie helper. Use compact/jwt or pass cookie data through the auth server."
732
+ );
733
+ }
734
+ if (strategy === "jwt") {
735
+ const payload = await verifyJwtHS256(sessionData, secret);
736
+ if (!payload) {
737
+ return null;
738
+ }
739
+ const sessionRecord = asObject(payload.session);
740
+ const userRecord = asObject(payload.user);
741
+ const updatedAt = payload.updatedAt;
742
+ if (!sessionRecord || !userRecord || typeof updatedAt !== "number") {
743
+ return null;
744
+ }
745
+ if (config?.version) {
746
+ const cookieVersion = typeof payload.version === "string" ? payload.version : "1";
747
+ const expectedVersion = typeof config.version === "string" ? config.version : await config.version(sessionRecord, userRecord);
748
+ if (cookieVersion !== expectedVersion) {
749
+ return null;
750
+ }
751
+ }
752
+ return {
753
+ session: sessionRecord,
754
+ user: userRecord,
755
+ updatedAt,
756
+ version: typeof payload.version === "string" ? payload.version : void 0
757
+ };
758
+ }
759
+ const compactPayload = parseJsonSafely(decodeBase64UrlToString(sessionData));
760
+ if (!compactPayload) {
761
+ return null;
762
+ }
763
+ const expectedSignature = await signHmacBase64Url(
764
+ secret,
765
+ JSON.stringify({
766
+ ...compactPayload.session,
767
+ expiresAt: compactPayload.expiresAt
768
+ })
769
+ );
770
+ if (expectedSignature !== compactPayload.signature) {
771
+ return null;
772
+ }
773
+ if (compactPayload.expiresAt <= Date.now()) {
774
+ return null;
775
+ }
776
+ const resolvedSession = compactPayload.session;
777
+ if (config?.version) {
778
+ const cookieVersion = resolvedSession.version || "1";
779
+ const expectedVersion = typeof config.version === "string" ? config.version : await config.version(resolvedSession.session, resolvedSession.user);
780
+ if (cookieVersion !== expectedVersion) {
781
+ return null;
782
+ }
783
+ }
784
+ const sessionObject = asObject(resolvedSession.session);
785
+ const userObject = asObject(resolvedSession.user);
786
+ if (!sessionObject || !userObject) {
787
+ return null;
788
+ }
789
+ return {
790
+ session: sessionObject,
791
+ user: userObject,
792
+ updatedAt: resolvedSession.updatedAt,
793
+ version: resolvedSession.version
794
+ };
795
+ };
158
796
 
159
797
  // package.json
160
798
  var package_default = {
161
- version: "2.4.1"
799
+ version: "2.6.0"
162
800
  };
163
801
 
164
802
  // src/sdk-version.ts
@@ -2699,38 +3337,730 @@ async function withRetry(config, fn) {
2699
3337
  await sleep(delay);
2700
3338
  }
2701
3339
  }
2702
- throw new Error("withRetry reached an unexpected state");
3340
+ throw new Error("withRetry reached an unexpected state");
3341
+ }
3342
+
3343
+ // src/db/module.ts
3344
+ function createDbModule(input) {
3345
+ const db = {
3346
+ from(table, options) {
3347
+ return input.from(table, options);
3348
+ },
3349
+ select(table, columns, options) {
3350
+ return input.from(table).select(columns, options);
3351
+ },
3352
+ insert(table, values, options) {
3353
+ return Array.isArray(values) ? input.from(table).insert(values, options) : input.from(table).insert(values, options);
3354
+ },
3355
+ upsert(table, values, options) {
3356
+ return Array.isArray(values) ? input.from(table).upsert(values, options) : input.from(table).upsert(values, options);
3357
+ },
3358
+ update(table, values, options) {
3359
+ return input.from(table).update(values, options);
3360
+ },
3361
+ delete(table, options) {
3362
+ return input.from(table).delete(options);
3363
+ },
3364
+ rpc(fn, args, options) {
3365
+ return input.rpc(fn, args, options);
3366
+ },
3367
+ query(query, options) {
3368
+ return input.query(query, options);
3369
+ }
3370
+ };
3371
+ return db;
3372
+ }
3373
+
3374
+ // src/storage/module.ts
3375
+ var storageSdkManifest = {
3376
+ namespace: "storage",
3377
+ basePath: "/storage",
3378
+ envelopeKinds: {
3379
+ raw: "response body is the payload",
3380
+ athena: "response body is { status, message, data }"
3381
+ },
3382
+ methods: [
3383
+ {
3384
+ name: "listStorageCatalogs",
3385
+ method: "GET",
3386
+ path: "/storage/catalogs",
3387
+ responseEnvelope: "raw",
3388
+ responseType: "{ data: S3CatalogItem[] }"
3389
+ },
3390
+ {
3391
+ name: "createStorageCatalog",
3392
+ method: "POST",
3393
+ path: "/storage/catalogs",
3394
+ requestType: "CreateStorageCatalogRequest",
3395
+ responseEnvelope: "raw",
3396
+ responseType: "S3CatalogItem"
3397
+ },
3398
+ {
3399
+ name: "updateStorageCatalog",
3400
+ method: "PATCH",
3401
+ path: "/storage/catalogs/{id}",
3402
+ pathParams: ["id"],
3403
+ requestType: "UpdateStorageCatalogRequest",
3404
+ responseEnvelope: "raw",
3405
+ responseType: "S3CatalogItem"
3406
+ },
3407
+ {
3408
+ name: "deleteStorageCatalog",
3409
+ method: "DELETE",
3410
+ path: "/storage/catalogs/{id}",
3411
+ pathParams: ["id"],
3412
+ responseEnvelope: "raw",
3413
+ responseType: "{ id: string; deleted: boolean }"
3414
+ },
3415
+ {
3416
+ name: "listStorageCredentials",
3417
+ method: "GET",
3418
+ path: "/storage/credentials",
3419
+ responseEnvelope: "raw",
3420
+ responseType: "{ data: S3CredentialListItem[] }"
3421
+ },
3422
+ {
3423
+ name: "createStorageUploadUrl",
3424
+ method: "POST",
3425
+ path: "/storage/files/upload-url",
3426
+ requestType: "CreateStorageUploadUrlRequest",
3427
+ responseEnvelope: "athena",
3428
+ responseType: "StorageUploadUrlResponse"
3429
+ },
3430
+ {
3431
+ name: "createStorageUploadUrls",
3432
+ method: "POST",
3433
+ path: "/storage/files/upload-urls",
3434
+ requestType: "CreateStorageUploadUrlsRequest",
3435
+ responseEnvelope: "athena",
3436
+ responseType: "StorageBatchUploadUrlResponse"
3437
+ },
3438
+ {
3439
+ name: "listStorageFiles",
3440
+ method: "POST",
3441
+ path: "/storage/files/list",
3442
+ requestType: "ListStorageFilesRequest",
3443
+ responseEnvelope: "athena",
3444
+ responseType: "StorageListFilesResponse"
3445
+ },
3446
+ {
3447
+ name: "getStorageFile",
3448
+ method: "GET",
3449
+ path: "/storage/files/{file_id}",
3450
+ pathParams: ["file_id"],
3451
+ responseEnvelope: "athena",
3452
+ responseType: "StorageFileMutationResponse"
3453
+ },
3454
+ {
3455
+ name: "getStorageFileUrl",
3456
+ method: "GET",
3457
+ path: "/storage/files/{file_id}/url",
3458
+ pathParams: ["file_id"],
3459
+ queryParams: ["purpose"],
3460
+ responseEnvelope: "athena",
3461
+ responseType: "PresignedFileUrlResponse"
3462
+ },
3463
+ {
3464
+ name: "getStorageFileProxy",
3465
+ method: "GET",
3466
+ path: "/storage/files/{file_id}/proxy",
3467
+ pathParams: ["file_id"],
3468
+ queryParams: ["purpose"],
3469
+ responseEnvelope: "raw",
3470
+ responseType: "Response",
3471
+ binary: true
3472
+ },
3473
+ {
3474
+ name: "updateStorageFile",
3475
+ method: "PATCH",
3476
+ path: "/storage/files/{file_id}",
3477
+ pathParams: ["file_id"],
3478
+ requestType: "UpdateStorageFileRequest",
3479
+ responseEnvelope: "athena",
3480
+ responseType: "StorageFileMutationResponse"
3481
+ },
3482
+ {
3483
+ name: "deleteStorageFile",
3484
+ method: "DELETE",
3485
+ path: "/storage/files/{file_id}",
3486
+ pathParams: ["file_id"],
3487
+ responseEnvelope: "athena",
3488
+ responseType: "StorageFileMutationResponse"
3489
+ },
3490
+ {
3491
+ name: "setStorageFileVisibility",
3492
+ method: "PATCH",
3493
+ path: "/storage/files/{file_id}/visibility",
3494
+ pathParams: ["file_id"],
3495
+ requestType: "SetStorageFileVisibilityRequest",
3496
+ responseEnvelope: "athena",
3497
+ responseType: "StorageFileMutationResponse"
3498
+ },
3499
+ {
3500
+ name: "deleteStorageFolder",
3501
+ method: "POST",
3502
+ path: "/storage/folders/delete",
3503
+ requestType: "DeleteStorageFolderRequest",
3504
+ responseEnvelope: "athena",
3505
+ responseType: "StorageFolderMutationResponse"
3506
+ },
3507
+ {
3508
+ name: "moveStorageFolder",
3509
+ method: "POST",
3510
+ path: "/storage/folders/move",
3511
+ requestType: "MoveStorageFolderRequest",
3512
+ responseEnvelope: "athena",
3513
+ responseType: "StorageFolderMutationResponse"
3514
+ }
3515
+ ]
3516
+ };
3517
+ var AthenaStorageErrorCode = {
3518
+ InvalidUrl: "INVALID_URL",
3519
+ NetworkError: "NETWORK_ERROR",
3520
+ HttpError: "HTTP_ERROR",
3521
+ InvalidJson: "INVALID_JSON",
3522
+ InvalidAthenaEnvelope: "INVALID_ATHENA_ENVELOPE",
3523
+ UnknownError: "UNKNOWN_ERROR"
3524
+ };
3525
+ var AthenaStorageError = class extends Error {
3526
+ code;
3527
+ athenaCode;
3528
+ kind;
3529
+ category;
3530
+ retryable;
3531
+ status;
3532
+ endpoint;
3533
+ method;
3534
+ requestId;
3535
+ hint;
3536
+ causeDetail;
3537
+ raw;
3538
+ normalized;
3539
+ __athenaNormalizedError;
3540
+ constructor(input) {
3541
+ super(input.message, { cause: input.cause });
3542
+ this.name = "AthenaStorageError";
3543
+ this.code = input.code;
3544
+ this.status = input.status;
3545
+ this.endpoint = input.endpoint;
3546
+ this.method = input.method;
3547
+ this.requestId = input.requestId;
3548
+ this.hint = input.hint;
3549
+ this.causeDetail = causeToString(input.cause);
3550
+ this.raw = input.raw ?? null;
3551
+ this.normalized = normalizeStorageErrorInput(input);
3552
+ this.__athenaNormalizedError = this.normalized;
3553
+ this.athenaCode = this.normalized.code;
3554
+ this.kind = this.normalized.kind;
3555
+ this.category = this.normalized.category;
3556
+ this.retryable = this.normalized.retryable;
3557
+ Object.defineProperty(this, "__athenaNormalizedError", {
3558
+ value: this.normalized,
3559
+ enumerable: false,
3560
+ configurable: false,
3561
+ writable: false
3562
+ });
3563
+ }
3564
+ toDetails() {
3565
+ return {
3566
+ code: this.code,
3567
+ athenaCode: this.athenaCode,
3568
+ kind: this.kind,
3569
+ category: this.category,
3570
+ retryable: this.retryable,
3571
+ message: this.message,
3572
+ status: this.status,
3573
+ endpoint: this.endpoint,
3574
+ method: this.method,
3575
+ requestId: this.requestId,
3576
+ hint: this.hint,
3577
+ cause: this.causeDetail,
3578
+ raw: this.raw
3579
+ };
3580
+ }
3581
+ };
3582
+ function isRecord5(value) {
3583
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
3584
+ }
3585
+ function causeToString(cause) {
3586
+ if (cause === void 0 || cause === null) return void 0;
3587
+ if (typeof cause === "string") return cause;
3588
+ if (cause instanceof Error && cause.message.trim()) return cause.message.trim();
3589
+ try {
3590
+ return JSON.stringify(cause);
3591
+ } catch {
3592
+ return String(cause);
3593
+ }
3594
+ }
3595
+ function storageGatewayCode(code) {
3596
+ if (code === "INVALID_URL") return "INVALID_URL";
3597
+ if (code === "NETWORK_ERROR") return "NETWORK_ERROR";
3598
+ if (code === "INVALID_JSON" || code === "INVALID_ATHENA_ENVELOPE") return "INVALID_JSON";
3599
+ if (code === "HTTP_ERROR") return "HTTP_ERROR";
3600
+ return "UNKNOWN_ERROR";
3601
+ }
3602
+ function headerValue(headers, names) {
3603
+ for (const name of names) {
3604
+ const value = headers.get(name);
3605
+ if (value?.trim()) return value.trim();
3606
+ }
3607
+ return void 0;
3608
+ }
3609
+ function storageOperationFromEndpoint(endpoint, method) {
3610
+ const endpointPath = String(endpoint).split("?")[0];
3611
+ for (const candidate of storageSdkManifest.methods) {
3612
+ if (candidate.method !== method) continue;
3613
+ const pattern = `^${candidate.path.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\\\{[^/]+\\\}/g, "[^/]+")}$`;
3614
+ if (new RegExp(pattern).test(endpointPath)) {
3615
+ return candidate.name;
3616
+ }
3617
+ }
3618
+ return `storage:${method.toLowerCase()}`;
3619
+ }
3620
+ function normalizeStorageErrorInput(input) {
3621
+ return normalizeAthenaError(
3622
+ {
3623
+ data: null,
3624
+ error: {
3625
+ message: input.message,
3626
+ gatewayCode: storageGatewayCode(input.code),
3627
+ status: input.status,
3628
+ raw: input.raw ?? input.cause ?? null
3629
+ },
3630
+ errorDetails: {
3631
+ code: storageGatewayCode(input.code),
3632
+ message: input.message,
3633
+ status: input.status,
3634
+ endpoint: input.endpoint,
3635
+ method: input.method,
3636
+ requestId: input.requestId,
3637
+ hint: input.hint,
3638
+ cause: causeToString(input.cause)
3639
+ },
3640
+ raw: input.raw ?? input.cause ?? null,
3641
+ status: input.status
3642
+ },
3643
+ { operation: storageOperationFromEndpoint(input.endpoint, input.method) }
3644
+ );
3645
+ }
3646
+ function createAthenaStorageError(input) {
3647
+ return new AthenaStorageError(input);
3648
+ }
3649
+ async function notifyStorageError(error, options, runtimeOptions) {
3650
+ const handlers = [runtimeOptions?.onError, options?.onError].filter(
3651
+ (handler) => typeof handler === "function"
3652
+ );
3653
+ for (const handler of handlers) {
3654
+ try {
3655
+ await handler(error);
3656
+ } catch {
3657
+ }
3658
+ }
3659
+ }
3660
+ async function rejectStorageError(input, options, runtimeOptions) {
3661
+ const error = createAthenaStorageError(input);
3662
+ await notifyStorageError(error, options, runtimeOptions);
3663
+ throw error;
3664
+ }
3665
+ function parseResponseBody3(rawText, contentType) {
3666
+ if (!rawText) {
3667
+ return { parsed: null, parseFailed: false };
3668
+ }
3669
+ const contentTypeSuggestsJson = contentType?.toLowerCase().includes("application/json") ?? false;
3670
+ const looksJson = contentTypeSuggestsJson || rawText.startsWith("{") || rawText.startsWith("[");
3671
+ if (!looksJson) {
3672
+ return { parsed: rawText, parseFailed: false };
3673
+ }
3674
+ try {
3675
+ return { parsed: JSON.parse(rawText), parseFailed: false };
3676
+ } catch {
3677
+ return { parsed: rawText, parseFailed: true };
3678
+ }
3679
+ }
3680
+ function appendQuery(path, query) {
3681
+ if (!query) return path;
3682
+ const params = new URLSearchParams();
3683
+ for (const [key, value] of Object.entries(query)) {
3684
+ if (value === void 0 || value === null) continue;
3685
+ params.set(key, String(value));
3686
+ }
3687
+ const queryText = params.toString();
3688
+ return queryText ? `${path}?${queryText}` : path;
3689
+ }
3690
+ function storagePath(path) {
3691
+ return path;
3692
+ }
3693
+ function withPathParam(path, name, value) {
3694
+ return path.replace(`{${name}}`, encodeURIComponent(value));
3695
+ }
3696
+ function resolveErrorMessage3(payload, fallback) {
3697
+ if (isRecord5(payload)) {
3698
+ const message = payload.message ?? payload.error ?? payload.details;
3699
+ if (typeof message === "string" && message.trim()) {
3700
+ return message.trim();
3701
+ }
3702
+ }
3703
+ if (typeof payload === "string" && payload.trim()) {
3704
+ return payload.trim();
3705
+ }
3706
+ return fallback;
3707
+ }
3708
+ function resolveErrorHint2(payload) {
3709
+ if (!isRecord5(payload)) return void 0;
3710
+ const hint = payload.hint ?? payload.suggestion;
3711
+ return typeof hint === "string" && hint.trim() ? hint.trim() : void 0;
3712
+ }
3713
+ function resolveErrorCause(payload) {
3714
+ if (!isRecord5(payload)) return void 0;
3715
+ const cause = payload.cause ?? payload.reason;
3716
+ return typeof cause === "string" && cause.trim() ? cause.trim() : void 0;
3717
+ }
3718
+ function storageCodeFromUnknown(error) {
3719
+ if (isAthenaGatewayError(error)) {
3720
+ if (error.code === "INVALID_URL") return "INVALID_URL";
3721
+ if (error.code === "NETWORK_ERROR") return "NETWORK_ERROR";
3722
+ if (error.code === "INVALID_JSON") return "INVALID_JSON";
3723
+ if (error.code === "HTTP_ERROR") return "HTTP_ERROR";
3724
+ }
3725
+ return "UNKNOWN_ERROR";
3726
+ }
3727
+ async function callStorageEndpoint(gateway, endpoint, method, envelope, payload, options, runtimeOptions) {
3728
+ let url;
3729
+ let headers;
3730
+ try {
3731
+ const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : gateway.baseUrl;
3732
+ url = buildAthenaGatewayUrl(baseUrl, endpoint);
3733
+ headers = gateway.buildHeaders(options);
3734
+ } catch (error) {
3735
+ return rejectStorageError(
3736
+ {
3737
+ code: storageCodeFromUnknown(error),
3738
+ message: error instanceof Error ? error.message : `Athena storage ${method} ${endpoint} failed before sending the request`,
3739
+ status: isAthenaGatewayError(error) ? error.status : 0,
3740
+ endpoint,
3741
+ method,
3742
+ raw: error,
3743
+ requestId: isAthenaGatewayError(error) ? error.requestId : void 0,
3744
+ hint: isAthenaGatewayError(error) ? error.hint : void 0,
3745
+ cause: error
3746
+ },
3747
+ options,
3748
+ runtimeOptions
3749
+ );
3750
+ }
3751
+ const requestInit = {
3752
+ method,
3753
+ headers,
3754
+ signal: options?.signal
3755
+ };
3756
+ if (payload !== void 0 && method !== "GET") {
3757
+ requestInit.body = JSON.stringify(payload);
3758
+ }
3759
+ let response;
3760
+ try {
3761
+ response = await fetch(url, requestInit);
3762
+ } catch (error) {
3763
+ const message = error instanceof Error ? error.message : String(error);
3764
+ return rejectStorageError(
3765
+ {
3766
+ code: "NETWORK_ERROR",
3767
+ message: `Network error while calling Athena storage ${method} ${endpoint}: ${message}`,
3768
+ status: 0,
3769
+ endpoint,
3770
+ method,
3771
+ cause: error
3772
+ },
3773
+ options,
3774
+ runtimeOptions
3775
+ );
3776
+ }
3777
+ let rawText;
3778
+ try {
3779
+ rawText = await response.text();
3780
+ } catch (error) {
3781
+ return rejectStorageError(
3782
+ {
3783
+ code: "NETWORK_ERROR",
3784
+ message: `Athena storage ${method} ${endpoint} response body could not be read`,
3785
+ status: response.status,
3786
+ endpoint,
3787
+ method,
3788
+ requestId: headerValue(response.headers, ["x-athena-request-id", "x-request-id", "request-id"]),
3789
+ cause: error
3790
+ },
3791
+ options,
3792
+ runtimeOptions
3793
+ );
3794
+ }
3795
+ const parsedBody = parseResponseBody3(rawText ?? "", response.headers.get("content-type"));
3796
+ const requestId = headerValue(response.headers, ["x-athena-request-id", "x-request-id", "request-id"]);
3797
+ if (parsedBody.parseFailed) {
3798
+ return rejectStorageError(
3799
+ {
3800
+ code: "INVALID_JSON",
3801
+ message: `Athena storage ${method} ${endpoint} returned malformed JSON`,
3802
+ status: response.status,
3803
+ endpoint,
3804
+ method,
3805
+ requestId,
3806
+ raw: parsedBody.parsed
3807
+ },
3808
+ options,
3809
+ runtimeOptions
3810
+ );
3811
+ }
3812
+ if (!response.ok) {
3813
+ return rejectStorageError(
3814
+ {
3815
+ code: "HTTP_ERROR",
3816
+ message: resolveErrorMessage3(
3817
+ parsedBody.parsed,
3818
+ `Athena storage ${method} ${endpoint} failed with status ${response.status}`
3819
+ ),
3820
+ status: response.status,
3821
+ endpoint,
3822
+ method,
3823
+ requestId,
3824
+ hint: resolveErrorHint2(parsedBody.parsed),
3825
+ cause: resolveErrorCause(parsedBody.parsed),
3826
+ raw: parsedBody.parsed
3827
+ },
3828
+ options,
3829
+ runtimeOptions
3830
+ );
3831
+ }
3832
+ if (envelope === "athena") {
3833
+ if (!isRecord5(parsedBody.parsed) || !("data" in parsedBody.parsed)) {
3834
+ return rejectStorageError(
3835
+ {
3836
+ code: "INVALID_ATHENA_ENVELOPE",
3837
+ message: `Athena storage ${method} ${endpoint} returned an invalid Athena envelope`,
3838
+ status: response.status,
3839
+ endpoint,
3840
+ method,
3841
+ requestId,
3842
+ raw: parsedBody.parsed
3843
+ },
3844
+ options,
3845
+ runtimeOptions
3846
+ );
3847
+ }
3848
+ return parsedBody.parsed.data;
3849
+ }
3850
+ return parsedBody.parsed;
3851
+ }
3852
+ async function callStorageBinaryEndpoint(gateway, endpoint, method, options, runtimeOptions) {
3853
+ let url;
3854
+ let headers;
3855
+ try {
3856
+ const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : gateway.baseUrl;
3857
+ url = buildAthenaGatewayUrl(baseUrl, endpoint);
3858
+ headers = gateway.buildHeaders(options);
3859
+ } catch (error) {
3860
+ return rejectStorageError(
3861
+ {
3862
+ code: storageCodeFromUnknown(error),
3863
+ message: error instanceof Error ? error.message : `Athena storage ${method} ${endpoint} failed before sending the request`,
3864
+ status: isAthenaGatewayError(error) ? error.status : 0,
3865
+ endpoint,
3866
+ method,
3867
+ raw: error,
3868
+ requestId: isAthenaGatewayError(error) ? error.requestId : void 0,
3869
+ hint: isAthenaGatewayError(error) ? error.hint : void 0,
3870
+ cause: error
3871
+ },
3872
+ options,
3873
+ runtimeOptions
3874
+ );
3875
+ }
3876
+ let response;
3877
+ try {
3878
+ response = await fetch(url, {
3879
+ method,
3880
+ headers,
3881
+ signal: options?.signal
3882
+ });
3883
+ } catch (error) {
3884
+ const message = error instanceof Error ? error.message : String(error);
3885
+ return rejectStorageError(
3886
+ {
3887
+ code: "NETWORK_ERROR",
3888
+ message: `Network error while calling Athena storage ${method} ${endpoint}: ${message}`,
3889
+ status: 0,
3890
+ endpoint,
3891
+ method,
3892
+ cause: error
3893
+ },
3894
+ options,
3895
+ runtimeOptions
3896
+ );
3897
+ }
3898
+ if (response.ok) {
3899
+ return response;
3900
+ }
3901
+ const requestId = headerValue(response.headers, ["x-athena-request-id", "x-request-id", "request-id"]);
3902
+ let rawErrorBody = null;
3903
+ try {
3904
+ const rawText = await response.text();
3905
+ const parsedBody = parseResponseBody3(rawText ?? "", response.headers.get("content-type"));
3906
+ rawErrorBody = parsedBody.parsed;
3907
+ } catch (error) {
3908
+ return rejectStorageError(
3909
+ {
3910
+ code: "NETWORK_ERROR",
3911
+ message: `Athena storage ${method} ${endpoint} error response body could not be read`,
3912
+ status: response.status,
3913
+ endpoint,
3914
+ method,
3915
+ requestId,
3916
+ cause: error
3917
+ },
3918
+ options,
3919
+ runtimeOptions
3920
+ );
3921
+ }
3922
+ return rejectStorageError(
3923
+ {
3924
+ code: "HTTP_ERROR",
3925
+ message: resolveErrorMessage3(
3926
+ rawErrorBody,
3927
+ `Athena storage ${method} ${endpoint} failed with status ${response.status}`
3928
+ ),
3929
+ status: response.status,
3930
+ endpoint,
3931
+ method,
3932
+ requestId,
3933
+ hint: resolveErrorHint2(rawErrorBody),
3934
+ cause: resolveErrorCause(rawErrorBody),
3935
+ raw: rawErrorBody
3936
+ },
3937
+ options,
3938
+ runtimeOptions
3939
+ );
2703
3940
  }
2704
-
2705
- // src/db/module.ts
2706
- function createDbModule(input) {
2707
- const db = {
2708
- from(table, options) {
2709
- return input.from(table, options);
3941
+ function createStorageModule(gateway, runtimeOptions) {
3942
+ return {
3943
+ listStorageCatalogs(options) {
3944
+ return callStorageEndpoint(gateway, storagePath("/storage/catalogs"), "GET", "raw", void 0, options, runtimeOptions);
2710
3945
  },
2711
- select(table, columns, options) {
2712
- return input.from(table).select(columns, options);
3946
+ createStorageCatalog(input, options) {
3947
+ return callStorageEndpoint(gateway, storagePath("/storage/catalogs"), "POST", "raw", input, options, runtimeOptions);
2713
3948
  },
2714
- insert(table, values, options) {
2715
- return Array.isArray(values) ? input.from(table).insert(values, options) : input.from(table).insert(values, options);
3949
+ updateStorageCatalog(id, input, options) {
3950
+ return callStorageEndpoint(
3951
+ gateway,
3952
+ storagePath(withPathParam("/storage/catalogs/{id}", "id", id)),
3953
+ "PATCH",
3954
+ "raw",
3955
+ input,
3956
+ options,
3957
+ runtimeOptions
3958
+ );
2716
3959
  },
2717
- upsert(table, values, options) {
2718
- return Array.isArray(values) ? input.from(table).upsert(values, options) : input.from(table).upsert(values, options);
3960
+ deleteStorageCatalog(id, options) {
3961
+ return callStorageEndpoint(
3962
+ gateway,
3963
+ storagePath(withPathParam("/storage/catalogs/{id}", "id", id)),
3964
+ "DELETE",
3965
+ "raw",
3966
+ void 0,
3967
+ options,
3968
+ runtimeOptions
3969
+ );
2719
3970
  },
2720
- update(table, values, options) {
2721
- return input.from(table).update(values, options);
3971
+ listStorageCredentials(options) {
3972
+ return callStorageEndpoint(gateway, storagePath("/storage/credentials"), "GET", "raw", void 0, options, runtimeOptions);
2722
3973
  },
2723
- delete(table, options) {
2724
- return input.from(table).delete(options);
3974
+ createStorageUploadUrl(input, options) {
3975
+ return callStorageEndpoint(
3976
+ gateway,
3977
+ storagePath("/storage/files/upload-url"),
3978
+ "POST",
3979
+ "athena",
3980
+ input,
3981
+ options,
3982
+ runtimeOptions
3983
+ );
2725
3984
  },
2726
- rpc(fn, args, options) {
2727
- return input.rpc(fn, args, options);
3985
+ createStorageUploadUrls(input, options) {
3986
+ return callStorageEndpoint(
3987
+ gateway,
3988
+ storagePath("/storage/files/upload-urls"),
3989
+ "POST",
3990
+ "athena",
3991
+ input,
3992
+ options,
3993
+ runtimeOptions
3994
+ );
2728
3995
  },
2729
- query(query, options) {
2730
- return input.query(query, options);
3996
+ listStorageFiles(input, options) {
3997
+ return callStorageEndpoint(gateway, storagePath("/storage/files/list"), "POST", "athena", input, options, runtimeOptions);
3998
+ },
3999
+ getStorageFile(fileId, options) {
4000
+ return callStorageEndpoint(
4001
+ gateway,
4002
+ storagePath(withPathParam("/storage/files/{file_id}", "file_id", fileId)),
4003
+ "GET",
4004
+ "athena",
4005
+ void 0,
4006
+ options,
4007
+ runtimeOptions
4008
+ );
4009
+ },
4010
+ getStorageFileUrl(fileId, query, options) {
4011
+ const path = appendQuery(
4012
+ withPathParam("/storage/files/{file_id}/url", "file_id", fileId),
4013
+ query
4014
+ );
4015
+ return callStorageEndpoint(gateway, storagePath(path), "GET", "athena", void 0, options, runtimeOptions);
4016
+ },
4017
+ getStorageFileProxy(fileId, query, options) {
4018
+ const path = appendQuery(
4019
+ withPathParam("/storage/files/{file_id}/proxy", "file_id", fileId),
4020
+ query
4021
+ );
4022
+ return callStorageBinaryEndpoint(gateway, storagePath(path), "GET", options, runtimeOptions);
4023
+ },
4024
+ updateStorageFile(fileId, input, options) {
4025
+ return callStorageEndpoint(
4026
+ gateway,
4027
+ storagePath(withPathParam("/storage/files/{file_id}", "file_id", fileId)),
4028
+ "PATCH",
4029
+ "athena",
4030
+ input,
4031
+ options,
4032
+ runtimeOptions
4033
+ );
4034
+ },
4035
+ deleteStorageFile(fileId, options) {
4036
+ return callStorageEndpoint(
4037
+ gateway,
4038
+ storagePath(withPathParam("/storage/files/{file_id}", "file_id", fileId)),
4039
+ "DELETE",
4040
+ "athena",
4041
+ void 0,
4042
+ options,
4043
+ runtimeOptions
4044
+ );
4045
+ },
4046
+ setStorageFileVisibility(fileId, input, options) {
4047
+ return callStorageEndpoint(
4048
+ gateway,
4049
+ storagePath(withPathParam("/storage/files/{file_id}/visibility", "file_id", fileId)),
4050
+ "PATCH",
4051
+ "athena",
4052
+ input,
4053
+ options,
4054
+ runtimeOptions
4055
+ );
4056
+ },
4057
+ deleteStorageFolder(input, options) {
4058
+ return callStorageEndpoint(gateway, storagePath("/storage/folders/delete"), "POST", "athena", input, options, runtimeOptions);
4059
+ },
4060
+ moveStorageFolder(input, options) {
4061
+ return callStorageEndpoint(gateway, storagePath("/storage/folders/move"), "POST", "athena", input, options, runtimeOptions);
2731
4062
  }
2732
4063
  };
2733
- return db;
2734
4064
  }
2735
4065
 
2736
4066
  // src/query-ast.ts
@@ -2760,7 +4090,7 @@ var BOOLEAN_SAFE_OPERATORS = /* @__PURE__ */ new Set([
2760
4090
  "ilike",
2761
4091
  "is"
2762
4092
  ]);
2763
- function isRecord5(value) {
4093
+ function isRecord6(value) {
2764
4094
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
2765
4095
  }
2766
4096
  function isUuidString(value) {
@@ -2773,7 +4103,7 @@ function shouldUseUuidTextComparison(column, value) {
2773
4103
  return typeof value === "string" && isUuidString(value) && isUuidIdentifierColumn(column);
2774
4104
  }
2775
4105
  function isRelationSelectNode(value) {
2776
- return isRecord5(value) && isRecord5(value.select);
4106
+ return isRecord6(value) && isRecord6(value.select);
2777
4107
  }
2778
4108
  function normalizeIdentifier(value, label) {
2779
4109
  const normalized = value.trim();
@@ -2829,7 +4159,7 @@ function compileRelationToken(key, node) {
2829
4159
  return `${prefix}${relationToken}(${nested})`;
2830
4160
  }
2831
4161
  function compileSelectShape(select) {
2832
- if (!isRecord5(select)) {
4162
+ if (!isRecord6(select)) {
2833
4163
  throw new Error("findMany select must be an object");
2834
4164
  }
2835
4165
  const tokens = [];
@@ -2853,7 +4183,7 @@ function compileSelectShape(select) {
2853
4183
  return tokens.join(",");
2854
4184
  }
2855
4185
  function selectShapeUsesRelationSchema(select) {
2856
- if (!isRecord5(select)) {
4186
+ if (!isRecord6(select)) {
2857
4187
  return false;
2858
4188
  }
2859
4189
  for (const rawValue of Object.values(select)) {
@@ -2871,7 +4201,7 @@ function selectShapeUsesRelationSchema(select) {
2871
4201
  }
2872
4202
  function compileColumnWhere(column, input) {
2873
4203
  const normalizedColumn = normalizeIdentifier(column, "where column");
2874
- if (!isRecord5(input)) {
4204
+ if (!isRecord6(input)) {
2875
4205
  return [buildGatewayCondition("eq", normalizedColumn, input)];
2876
4206
  }
2877
4207
  const conditions = [];
@@ -2899,7 +4229,7 @@ function compileColumnWhere(column, input) {
2899
4229
  return conditions;
2900
4230
  }
2901
4231
  function compileBooleanExpressionTerms(clause, label) {
2902
- if (!isRecord5(clause)) {
4232
+ if (!isRecord6(clause)) {
2903
4233
  throw new Error(`findMany where.${label} clauses must be objects`);
2904
4234
  }
2905
4235
  const entries = Object.entries(clause).filter(([, value]) => value !== void 0);
@@ -2908,7 +4238,7 @@ function compileBooleanExpressionTerms(clause, label) {
2908
4238
  }
2909
4239
  const [rawColumn, rawValue] = entries[0];
2910
4240
  const column = normalizeIdentifier(rawColumn, `where.${label} column`);
2911
- if (!isRecord5(rawValue)) {
4241
+ if (!isRecord6(rawValue)) {
2912
4242
  return [`${column}.eq.${stringifyFilterValue(rawValue)}`];
2913
4243
  }
2914
4244
  const operatorEntries = Object.entries(rawValue).filter(([, value]) => value !== void 0);
@@ -2932,7 +4262,7 @@ function compileWhere(where) {
2932
4262
  if (where === void 0) {
2933
4263
  return void 0;
2934
4264
  }
2935
- if (!isRecord5(where)) {
4265
+ if (!isRecord6(where)) {
2936
4266
  throw new Error("findMany where must be an object");
2937
4267
  }
2938
4268
  const conditions = [];
@@ -2982,7 +4312,7 @@ function compileOrderBy(orderBy) {
2982
4312
  if (orderBy === void 0) {
2983
4313
  return void 0;
2984
4314
  }
2985
- if (!isRecord5(orderBy)) {
4315
+ if (!isRecord6(orderBy)) {
2986
4316
  throw new Error("findMany orderBy must be an object");
2987
4317
  }
2988
4318
  if ("column" in orderBy) {
@@ -3157,11 +4487,11 @@ function toFindManyAstOrder(order) {
3157
4487
  ascending: order.direction !== "descending"
3158
4488
  };
3159
4489
  }
3160
- function isRecord6(value) {
4490
+ function isRecord7(value) {
3161
4491
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
3162
4492
  }
3163
4493
  function normalizeFindManyAstColumnPredicate(value) {
3164
- if (!isRecord6(value)) {
4494
+ if (!isRecord7(value)) {
3165
4495
  return {
3166
4496
  eq: value
3167
4497
  };
@@ -3185,7 +4515,7 @@ function normalizeFindManyAstBooleanOperand(clause) {
3185
4515
  return normalized;
3186
4516
  }
3187
4517
  function normalizeFindManyAstWhere(where) {
3188
- if (!where || !isRecord6(where)) {
4518
+ if (!where || !isRecord7(where)) {
3189
4519
  return where;
3190
4520
  }
3191
4521
  const normalized = {};
@@ -3199,7 +4529,7 @@ function normalizeFindManyAstWhere(where) {
3199
4529
  );
3200
4530
  continue;
3201
4531
  }
3202
- if (key === "not" && isRecord6(value)) {
4532
+ if (key === "not" && isRecord7(value)) {
3203
4533
  normalized.not = normalizeFindManyAstBooleanOperand(
3204
4534
  value
3205
4535
  );
@@ -3210,7 +4540,7 @@ function normalizeFindManyAstWhere(where) {
3210
4540
  return normalized;
3211
4541
  }
3212
4542
  function predicateRequiresUuidQueryFallback(column, value) {
3213
- if (!isRecord6(value)) {
4543
+ if (!isRecord7(value)) {
3214
4544
  return shouldUseUuidTextComparison(column, value);
3215
4545
  }
3216
4546
  const eqValue = value.eq;
@@ -3228,7 +4558,7 @@ function booleanOperandRequiresUuidQueryFallback(clause) {
3228
4558
  return false;
3229
4559
  }
3230
4560
  function findManyAstWhereRequiresLegacyTransport(where) {
3231
- if (!where || !isRecord6(where)) {
4561
+ if (!where || !isRecord7(where)) {
3232
4562
  return false;
3233
4563
  }
3234
4564
  for (const [key, value] of Object.entries(where)) {
@@ -3243,7 +4573,7 @@ function findManyAstWhereRequiresLegacyTransport(where) {
3243
4573
  }
3244
4574
  continue;
3245
4575
  }
3246
- if (key === "not" && isRecord6(value)) {
4576
+ if (key === "not" && isRecord7(value)) {
3247
4577
  if (booleanOperandRequiresUuidQueryFallback(value)) {
3248
4578
  return true;
3249
4579
  }
@@ -3445,7 +4775,7 @@ async function executeExperimentalRead(experimental, runner) {
3445
4775
  throw error;
3446
4776
  }
3447
4777
  }
3448
- function isRecord7(value) {
4778
+ function isRecord8(value) {
3449
4779
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
3450
4780
  }
3451
4781
  function firstNonEmptyString2(...values) {
@@ -3457,8 +4787,8 @@ function firstNonEmptyString2(...values) {
3457
4787
  return void 0;
3458
4788
  }
3459
4789
  function resolveStructuredErrorPayload2(raw) {
3460
- if (!isRecord7(raw)) return null;
3461
- return isRecord7(raw.error) ? raw.error : raw;
4790
+ if (!isRecord8(raw)) return null;
4791
+ return isRecord8(raw.error) ? raw.error : raw;
3462
4792
  }
3463
4793
  function resolveStructuredErrorDetails(payload, message) {
3464
4794
  if (!payload || !("details" in payload)) {
@@ -3474,7 +4804,7 @@ function resolveStructuredErrorDetails(payload, message) {
3474
4804
  return details;
3475
4805
  }
3476
4806
  function createResultError(response, result, normalized) {
3477
- const rawRecord = isRecord7(response.raw) ? response.raw : null;
4807
+ const rawRecord = isRecord8(response.raw) ? response.raw : null;
3478
4808
  const payload = resolveStructuredErrorPayload2(response.raw);
3479
4809
  const message = firstNonEmptyString2(
3480
4810
  response.error,
@@ -4937,7 +6267,7 @@ function createClientFromConfig(config) {
4937
6267
  };
4938
6268
  const query = createQueryBuilder(gateway, formatGatewayResult, config.experimental, queryTracer);
4939
6269
  const db = createDbModule({ from, rpc, query });
4940
- return {
6270
+ const sdkClient = {
4941
6271
  from,
4942
6272
  db,
4943
6273
  rpc,
@@ -4945,6 +6275,14 @@ function createClientFromConfig(config) {
4945
6275
  verifyConnection: gateway.verifyConnection,
4946
6276
  auth: auth.auth
4947
6277
  };
6278
+ if (config.experimental?.athenaStorageBackend) {
6279
+ const storageClient = {
6280
+ ...sdkClient,
6281
+ storage: createStorageModule(gateway, config.experimental.storage)
6282
+ };
6283
+ return storageClient;
6284
+ }
6285
+ return sdkClient;
4948
6286
  }
4949
6287
  var DEFAULT_BACKEND = { type: "athena" };
4950
6288
  function toBackendConfig(b) {
@@ -4975,6 +6313,12 @@ function mergeExperimentalOptions(current, next) {
4975
6313
  ...next.traceQueries
4976
6314
  };
4977
6315
  }
6316
+ if (current?.storage || next.storage) {
6317
+ merged.storage = {
6318
+ ...current?.storage ?? {},
6319
+ ...next.storage ?? {}
6320
+ };
6321
+ }
4978
6322
  return merged;
4979
6323
  }
4980
6324
  var AthenaClientBuilderImpl = class {
@@ -5011,7 +6355,7 @@ var AthenaClientBuilderImpl = class {
5011
6355
  }
5012
6356
  experimental(options) {
5013
6357
  this.experimentalOptions = mergeExperimentalOptions(this.experimentalOptions, options);
5014
- return this;
6358
+ return options.athenaStorageBackend ? this : this;
5015
6359
  }
5016
6360
  options(options) {
5017
6361
  if (options.client !== void 0) {
@@ -5032,7 +6376,7 @@ var AthenaClientBuilderImpl = class {
5032
6376
  if (options.experimental !== void 0) {
5033
6377
  this.experimentalOptions = mergeExperimentalOptions(this.experimentalOptions, options.experimental);
5034
6378
  }
5035
- return this;
6379
+ return options.experimental?.athenaStorageBackend ? this : this;
5036
6380
  }
5037
6381
  build() {
5038
6382
  if (!this.baseUrl || !this.apiKey) {
@@ -5663,7 +7007,7 @@ function resolveNullishValue(mode) {
5663
7007
  if (mode === "null") return null;
5664
7008
  return "";
5665
7009
  }
5666
- function isRecord8(value) {
7010
+ function isRecord9(value) {
5667
7011
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
5668
7012
  }
5669
7013
  function isNullableColumn(model, key) {
@@ -5672,7 +7016,7 @@ function isNullableColumn(model, key) {
5672
7016
  }
5673
7017
  function toModelFormDefaults(model, values, options) {
5674
7018
  const source = values;
5675
- if (!isRecord8(source)) {
7019
+ if (!isRecord9(source)) {
5676
7020
  return {};
5677
7021
  }
5678
7022
  const mode = options?.nullishMode ?? "empty-string";
@@ -6103,6 +7447,90 @@ async function loadGeneratorConfig(options = {}) {
6103
7447
  }
6104
7448
  }
6105
7449
 
7450
+ // src/generator/env.ts
7451
+ function readEnvStringValue2(key) {
7452
+ if (typeof process === "undefined" || !process.env) {
7453
+ return void 0;
7454
+ }
7455
+ const value = process.env[key];
7456
+ if (typeof value !== "string") {
7457
+ return void 0;
7458
+ }
7459
+ const trimmed = value.trim();
7460
+ return trimmed.length > 0 ? trimmed : void 0;
7461
+ }
7462
+ function throwMissingEnvVar(key) {
7463
+ throw new Error(
7464
+ `Generator config env var ${key} is missing or empty. Set ${key} or provide a default value.`
7465
+ );
7466
+ }
7467
+ function resolveEnvValue(key, options, resolver) {
7468
+ const rawValue = readEnvStringValue2(key);
7469
+ if (rawValue === void 0) {
7470
+ if (options?.default !== void 0) {
7471
+ return options.default;
7472
+ }
7473
+ if (options?.optional) {
7474
+ return void 0;
7475
+ }
7476
+ return throwMissingEnvVar(key);
7477
+ }
7478
+ return resolver(rawValue);
7479
+ }
7480
+ function resolveStringEnv(key, options) {
7481
+ return resolveEnvValue(key, options, (value) => value);
7482
+ }
7483
+ function resolveBooleanEnv(key, options) {
7484
+ return resolveEnvValue(key, options, (value) => parseBooleanFlag2(value, false));
7485
+ }
7486
+ function resolveListEnv(key, options) {
7487
+ return resolveEnvValue(key, options, (value) => {
7488
+ const separator = options?.separator ?? ",";
7489
+ return value.split(separator).map((entry) => entry.trim()).filter((entry, index, entries) => entry.length > 0 && entries.indexOf(entry) === index);
7490
+ })?.slice();
7491
+ }
7492
+ function resolveJsonEnv(key, options) {
7493
+ return resolveEnvValue(key, options, (value) => {
7494
+ try {
7495
+ return JSON.parse(value);
7496
+ } catch (error) {
7497
+ const message = error instanceof Error ? error.message : String(error);
7498
+ throw new Error(`Generator config env var ${key} must contain valid JSON. ${message}`);
7499
+ }
7500
+ });
7501
+ }
7502
+ function resolveOneOfEnv(key, allowedValues, options) {
7503
+ return resolveEnvValue(key, options, (value) => {
7504
+ if (allowedValues.includes(value)) {
7505
+ return value;
7506
+ }
7507
+ throw new Error(
7508
+ `Generator config env var ${key} must be one of: ${allowedValues.join(", ")}. Received: ${value}.`
7509
+ );
7510
+ });
7511
+ }
7512
+ function generatorEnvString(key, options) {
7513
+ return resolveStringEnv(key, options);
7514
+ }
7515
+ function generatorEnvBoolean(key, options) {
7516
+ return resolveBooleanEnv(key, options);
7517
+ }
7518
+ function generatorEnvList(key, options) {
7519
+ return resolveListEnv(key, options);
7520
+ }
7521
+ function generatorEnvJson(key, options) {
7522
+ return resolveJsonEnv(key, options);
7523
+ }
7524
+ function generatorEnvOneOf(key, allowedValues, options) {
7525
+ return resolveOneOfEnv(key, allowedValues, options);
7526
+ }
7527
+ var generatorEnv = Object.assign(generatorEnvString, {
7528
+ boolean: generatorEnvBoolean,
7529
+ list: generatorEnvList,
7530
+ json: generatorEnvJson,
7531
+ oneOf: generatorEnvOneOf
7532
+ });
7533
+
6106
7534
  // src/utils/slugify.ts
6107
7535
  function slugify(input) {
6108
7536
  return input.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
@@ -6860,6 +8288,433 @@ async function runSchemaGenerator(options = {}) {
6860
8288
  };
6861
8289
  }
6862
8290
 
6863
- 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 };
8291
+ // src/auth/server.ts
8292
+ var DEFAULT_AUTH_BASE_PATH = "/api/auth";
8293
+ var ATHENA_AUTH_BASE_ERROR_CODES = {
8294
+ HANDLER_NOT_CONFIGURED: "HANDLER_NOT_CONFIGURED",
8295
+ INVALID_BASE_URL: "INVALID_BASE_URL",
8296
+ UNTRUSTED_HOST: "UNTRUSTED_HOST"
8297
+ };
8298
+ function capitalize2(value) {
8299
+ return value.length > 0 ? `${value[0]?.toUpperCase()}${value.slice(1)}` : value;
8300
+ }
8301
+ function serializeSetCookieValue(name, value, attributes) {
8302
+ const parts = [`${name}=${encodeURIComponent(value)}`];
8303
+ const knownKeys = /* @__PURE__ */ new Set([
8304
+ "maxAge",
8305
+ "expires",
8306
+ "domain",
8307
+ "path",
8308
+ "secure",
8309
+ "httpOnly",
8310
+ "partitioned",
8311
+ "sameSite"
8312
+ ]);
8313
+ if (attributes.maxAge !== void 0) {
8314
+ parts.push(`Max-Age=${Math.trunc(attributes.maxAge)}`);
8315
+ }
8316
+ if (attributes.expires instanceof Date) {
8317
+ parts.push(`Expires=${attributes.expires.toUTCString()}`);
8318
+ }
8319
+ if (attributes.domain) {
8320
+ parts.push(`Domain=${attributes.domain}`);
8321
+ }
8322
+ if (attributes.path) {
8323
+ parts.push(`Path=${attributes.path}`);
8324
+ }
8325
+ if (attributes.secure) {
8326
+ parts.push("Secure");
8327
+ }
8328
+ if (attributes.httpOnly) {
8329
+ parts.push("HttpOnly");
8330
+ }
8331
+ if (attributes.partitioned) {
8332
+ parts.push("Partitioned");
8333
+ }
8334
+ if (attributes.sameSite) {
8335
+ parts.push(`SameSite=${capitalize2(attributes.sameSite)}`);
8336
+ }
8337
+ for (const [key, rawValue] of Object.entries(attributes)) {
8338
+ if (knownKeys.has(key) || rawValue === void 0 || rawValue === null || rawValue === false) {
8339
+ continue;
8340
+ }
8341
+ if (rawValue === true) {
8342
+ parts.push(key);
8343
+ continue;
8344
+ }
8345
+ parts.push(`${key}=${String(rawValue)}`);
8346
+ }
8347
+ return parts.join("; ");
8348
+ }
8349
+ function readCookieFromHeaders(headers, name) {
8350
+ const cookieHeader = headers?.get("cookie");
8351
+ if (!cookieHeader) {
8352
+ return void 0;
8353
+ }
8354
+ return parseCookies(cookieHeader).get(name);
8355
+ }
8356
+ function isRecord10(value) {
8357
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
8358
+ }
8359
+ function resolveSessionCandidate(value) {
8360
+ if (!isRecord10(value)) {
8361
+ return null;
8362
+ }
8363
+ const session = isRecord10(value.session) ? value.session : void 0;
8364
+ const user = isRecord10(value.user) ? value.user : void 0;
8365
+ if (session && typeof session.token === "string" && session.token.length > 0 && user) {
8366
+ return {
8367
+ session,
8368
+ user
8369
+ };
8370
+ }
8371
+ return null;
8372
+ }
8373
+ function inferSessionPair(returned) {
8374
+ return resolveSessionCandidate(returned) ?? (isRecord10(returned) ? resolveSessionCandidate(returned.data) : null) ?? (isRecord10(returned) ? resolveSessionCandidate(returned.session) : null);
8375
+ }
8376
+ function resolveResponseHeaders(ctx) {
8377
+ if (ctx.context.responseHeaders instanceof Headers) {
8378
+ return ctx.context.responseHeaders;
8379
+ }
8380
+ const headers = new Headers();
8381
+ ctx.context.responseHeaders = headers;
8382
+ return headers;
8383
+ }
8384
+ function normalizeBaseURL(baseURL) {
8385
+ return baseURL.replace(/\/$/, "");
8386
+ }
8387
+ function normalizeBasePath(basePath) {
8388
+ if (!basePath || basePath === "/") {
8389
+ return DEFAULT_AUTH_BASE_PATH;
8390
+ }
8391
+ const normalized = basePath.startsWith("/") ? basePath : `/${basePath}`;
8392
+ return normalized.endsWith("/") && normalized.length > 1 ? normalized.slice(0, -1) : normalized;
8393
+ }
8394
+ function isDynamicBaseURLConfig2(baseURL) {
8395
+ return typeof baseURL === "object" && baseURL !== null && "allowedHosts" in baseURL && Array.isArray(baseURL.allowedHosts);
8396
+ }
8397
+ function getRequestUrl(request) {
8398
+ try {
8399
+ return new URL(request.url);
8400
+ } catch {
8401
+ return new URL("http://localhost");
8402
+ }
8403
+ }
8404
+ function getRequestHost(request, url) {
8405
+ const forwardedHost = request.headers.get("x-forwarded-host")?.split(",")[0]?.trim();
8406
+ const host = forwardedHost || request.headers.get("host") || url.host;
8407
+ return host || null;
8408
+ }
8409
+ function getRequestProtocol(request, configuredProtocol, url) {
8410
+ if (configuredProtocol === "http" || configuredProtocol === "https") {
8411
+ return configuredProtocol;
8412
+ }
8413
+ const forwardedProto = request.headers.get("x-forwarded-proto")?.split(",")[0]?.trim();
8414
+ if (forwardedProto === "http" || forwardedProto === "https") {
8415
+ return forwardedProto;
8416
+ }
8417
+ if (url.protocol === "http:" || url.protocol === "https:") {
8418
+ return url.protocol.slice(0, -1);
8419
+ }
8420
+ return "http";
8421
+ }
8422
+ function resolveRequestBaseURL(baseURL, request) {
8423
+ if (typeof baseURL === "string") {
8424
+ return normalizeBaseURL(baseURL);
8425
+ }
8426
+ const requestUrl = getRequestUrl(request);
8427
+ const host = getRequestHost(request, requestUrl);
8428
+ if (!host) {
8429
+ return null;
8430
+ }
8431
+ if (isDynamicBaseURLConfig2(baseURL)) {
8432
+ const allowedHosts = baseURL.allowedHosts ?? [];
8433
+ if (allowedHosts.length > 0 && !allowedHosts.includes(host)) {
8434
+ return null;
8435
+ }
8436
+ }
8437
+ const protocol = typeof baseURL === "object" && baseURL !== null ? getRequestProtocol(request, baseURL.protocol, requestUrl) : getRequestProtocol(request, void 0, requestUrl);
8438
+ return `${protocol}://${host}`;
8439
+ }
8440
+ function getOrigin(baseURL) {
8441
+ if (!baseURL) {
8442
+ return void 0;
8443
+ }
8444
+ try {
8445
+ return new URL(baseURL).origin;
8446
+ } catch {
8447
+ return void 0;
8448
+ }
8449
+ }
8450
+ async function resolveTrustedOrigins(config, baseURL, request) {
8451
+ const resolved = typeof config.trustedOrigins === "function" ? await config.trustedOrigins(request) : config.trustedOrigins ?? [];
8452
+ const values = [
8453
+ getOrigin(baseURL),
8454
+ ...resolved
8455
+ ];
8456
+ return Array.from(new Set(values.filter((value) => typeof value === "string" && value.length > 0)));
8457
+ }
8458
+ async function resolveTrustedProviders(config, request) {
8459
+ const configured = typeof config.trustedProviders === "function" ? await config.trustedProviders(request) : config.trustedProviders ?? [];
8460
+ const values = [
8461
+ ...Object.keys(config.socialProviders ?? {}),
8462
+ ...configured
8463
+ ];
8464
+ return Array.from(new Set(values.filter((value) => typeof value === "string" && value.length > 0)));
8465
+ }
8466
+ function createJsonResponse(payload, init) {
8467
+ const headers = new Headers(init?.headers);
8468
+ if (!headers.has("content-type")) {
8469
+ headers.set("content-type", "application/json; charset=utf-8");
8470
+ }
8471
+ return new Response(JSON.stringify(payload), {
8472
+ ...init,
8473
+ headers
8474
+ });
8475
+ }
8476
+ function mergeResponseHeaders(response, headers) {
8477
+ return new Response(response.body, {
8478
+ status: response.status,
8479
+ statusText: response.statusText,
8480
+ headers
8481
+ });
8482
+ }
8483
+ function defineAthenaAuthConfig(config) {
8484
+ return config;
8485
+ }
8486
+ function athenaAuth(config) {
8487
+ const normalizedBasePath = normalizeBasePath(config.basePath);
8488
+ const staticBaseURL = typeof config.baseURL === "string" ? normalizeBaseURL(config.baseURL) : void 0;
8489
+ const runtime = {
8490
+ baseURL: staticBaseURL,
8491
+ basePath: normalizedBasePath,
8492
+ secret: config.secret,
8493
+ cookies: {
8494
+ session: config.session,
8495
+ advanced: config.advanced
8496
+ }
8497
+ };
8498
+ const resolvedDatabase = typeof config.database === "function" ? config.database(runtime) : config.database;
8499
+ const cookies = getCookies({
8500
+ baseURL: staticBaseURL ?? config.baseURL,
8501
+ session: config.session,
8502
+ advanced: config.advanced
8503
+ });
8504
+ const auth = {};
8505
+ const createCookieContext = (input = {}) => {
8506
+ const responseHeaders = input.responseHeaders ?? new Headers();
8507
+ const runtimeHeaders = input.headers;
8508
+ const authCookies = input.cookies ?? auth.cookies;
8509
+ const setCookie = input.setCookie ?? ((name, value, attributes) => {
8510
+ responseHeaders.append(
8511
+ "set-cookie",
8512
+ serializeSetCookieValue(name, value, attributes)
8513
+ );
8514
+ });
8515
+ return {
8516
+ headers: runtimeHeaders,
8517
+ getCookie: input.getCookie ?? ((name) => readCookieFromHeaders(runtimeHeaders, name)),
8518
+ setCookie,
8519
+ logger: input.logger,
8520
+ setSignedCookie: input.setSignedCookie,
8521
+ getSignedCookie: input.getSignedCookie,
8522
+ context: {
8523
+ secret: runtime.secret,
8524
+ authCookies,
8525
+ sessionConfig: {
8526
+ expiresIn: config.session?.expiresIn
8527
+ },
8528
+ options: {
8529
+ session: {
8530
+ cookieCache: config.session?.cookieCache
8531
+ },
8532
+ account: {
8533
+ storeAccountCookie: true
8534
+ }
8535
+ },
8536
+ setNewSession: input.setNewSession
8537
+ }
8538
+ };
8539
+ };
8540
+ const setSession = async (input, session, dontRememberMe, overrides) => {
8541
+ const cookieContext = createCookieContext(input);
8542
+ await setSessionCookie(cookieContext, session, dontRememberMe, overrides);
8543
+ };
8544
+ const clearSession = (input, skipDontRememberMe) => {
8545
+ const cookieContext = createCookieContext(input);
8546
+ deleteSessionCookie(cookieContext, skipDontRememberMe);
8547
+ };
8548
+ const applyResponseCookies = async (ctx) => {
8549
+ const responseHeaders = resolveResponseHeaders(ctx);
8550
+ const session = ctx.context.setSession ?? inferSessionPair(ctx.context.returned);
8551
+ if (ctx.context.clearSession) {
8552
+ clearSession({
8553
+ headers: ctx.headers,
8554
+ responseHeaders
8555
+ });
8556
+ }
8557
+ if (session) {
8558
+ await setSession(
8559
+ {
8560
+ headers: ctx.headers,
8561
+ responseHeaders
8562
+ },
8563
+ session,
8564
+ ctx.context.dontRememberMe,
8565
+ ctx.context.cookieOverrides
8566
+ );
8567
+ }
8568
+ return responseHeaders;
8569
+ };
8570
+ const runAfterHooks = async (ctx) => {
8571
+ for (const plugin of auth.plugins) {
8572
+ for (const hook of plugin.hooks?.after ?? []) {
8573
+ if (!hook.matcher(ctx)) {
8574
+ continue;
8575
+ }
8576
+ await hook.handler({
8577
+ ...ctx,
8578
+ auth
8579
+ });
8580
+ }
8581
+ }
8582
+ return ctx;
8583
+ };
8584
+ const resolveRequestContext = async (request) => {
8585
+ const requestUrl = getRequestUrl(request);
8586
+ const resolvedBaseURL = resolveRequestBaseURL(config.baseURL, request);
8587
+ if (!resolvedBaseURL) {
8588
+ throw new Error(
8589
+ isDynamicBaseURLConfig2(config.baseURL) ? "Could not resolve base URL from request. Check allowedHosts/baseURL." : "Could not resolve base URL from request."
8590
+ );
8591
+ }
8592
+ const requestCookies = getCookies({
8593
+ baseURL: resolvedBaseURL,
8594
+ session: config.session,
8595
+ advanced: config.advanced
8596
+ });
8597
+ const trustedOrigins = await resolveTrustedOrigins(config, resolvedBaseURL, request);
8598
+ const trustedProviders = await resolveTrustedProviders(config, request);
8599
+ return {
8600
+ auth,
8601
+ request,
8602
+ url: requestUrl,
8603
+ path: requestUrl.pathname,
8604
+ basePath: normalizedBasePath,
8605
+ baseURL: resolvedBaseURL,
8606
+ origin: getOrigin(resolvedBaseURL) ?? resolvedBaseURL,
8607
+ headers: request.headers,
8608
+ cookies: requestCookies,
8609
+ trustedOrigins,
8610
+ trustedProviders,
8611
+ options: config,
8612
+ runtime: {
8613
+ ...runtime,
8614
+ baseURL: resolvedBaseURL
8615
+ },
8616
+ database: auth.database,
8617
+ socialProviders: auth.socialProviders
8618
+ };
8619
+ };
8620
+ const handler = async (request) => {
8621
+ const requestContext = await resolveRequestContext(request);
8622
+ if (typeof config.handler !== "function") {
8623
+ return createJsonResponse(
8624
+ {
8625
+ ok: false,
8626
+ code: ATHENA_AUTH_BASE_ERROR_CODES.HANDLER_NOT_CONFIGURED,
8627
+ error: "No native auth handler was configured for this Athena auth instance.",
8628
+ path: requestContext.path,
8629
+ basePath: requestContext.basePath
8630
+ },
8631
+ { status: 501 }
8632
+ );
8633
+ }
8634
+ const result = await config.handler(requestContext);
8635
+ if (result instanceof Response) {
8636
+ return result;
8637
+ }
8638
+ const response = result.response ?? (result.returned !== void 0 ? createJsonResponse(result.returned) : new Response(null, { status: 204 }));
8639
+ const responseHeaders = new Headers(response.headers);
8640
+ await runAfterHooks({
8641
+ path: requestContext.path,
8642
+ headers: request.headers,
8643
+ context: {
8644
+ responseHeaders,
8645
+ returned: result.returned,
8646
+ setSession: result.setSession,
8647
+ clearSession: result.clearSession,
8648
+ dontRememberMe: result.dontRememberMe,
8649
+ cookieOverrides: result.cookieOverrides
8650
+ }
8651
+ });
8652
+ return mergeResponseHeaders(response, responseHeaders);
8653
+ };
8654
+ const api = Object.assign(
8655
+ {
8656
+ applyResponseCookies,
8657
+ clearSession,
8658
+ createCookieContext,
8659
+ getCookieCache,
8660
+ getSessionCookie,
8661
+ resolveRequestContext,
8662
+ runAfterHooks,
8663
+ setSession
8664
+ },
8665
+ config.api ?? {}
8666
+ );
8667
+ const $ERROR_CODES = {
8668
+ ...auth.plugins?.reduce((acc, plugin) => {
8669
+ if (plugin.$ERROR_CODES) {
8670
+ return {
8671
+ ...acc,
8672
+ ...plugin.$ERROR_CODES
8673
+ };
8674
+ }
8675
+ return acc;
8676
+ }, {}),
8677
+ ...config.errorCodes ?? {},
8678
+ ...ATHENA_AUTH_BASE_ERROR_CODES
8679
+ };
8680
+ Object.assign(auth, {
8681
+ config,
8682
+ options: config,
8683
+ runtime,
8684
+ database: resolvedDatabase,
8685
+ socialProviders: config.socialProviders ?? {},
8686
+ plugins: [...config.plugins ?? []],
8687
+ cookies,
8688
+ api,
8689
+ $ERROR_CODES,
8690
+ createCookieContext,
8691
+ setSession,
8692
+ clearSession,
8693
+ applyResponseCookies,
8694
+ runAfterHooks,
8695
+ resolveRequestContext,
8696
+ handler
8697
+ });
8698
+ auth.$context = Promise.all([
8699
+ resolveTrustedOrigins(config, staticBaseURL),
8700
+ resolveTrustedProviders(config)
8701
+ ]).then(([trustedOrigins, trustedProviders]) => ({
8702
+ auth,
8703
+ options: config,
8704
+ runtime,
8705
+ basePath: normalizedBasePath,
8706
+ baseURL: staticBaseURL,
8707
+ origin: getOrigin(staticBaseURL),
8708
+ database: auth.database,
8709
+ socialProviders: auth.socialProviders,
8710
+ plugins: auth.plugins,
8711
+ cookies: auth.cookies,
8712
+ trustedOrigins,
8713
+ trustedProviders
8714
+ }));
8715
+ return auth;
8716
+ }
8717
+
8718
+ 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 };
6864
8719
  //# sourceMappingURL=index.js.map
6865
8720
  //# sourceMappingURL=index.js.map