@better-auth/infra 0.4.7 → 0.4.8

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.
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { i as INFRA_USER_AGENT, n as INFRA_API_URL, o as PLUGIN_VERSION, r as INFRA_KV_URL } from "./constants-BypXAAvQ.mjs";
2
- import { a as createAPI, n as hash$1, o as createKV, r as hmacSha256Hex } from "./crypto-C9Iqqv8l.mjs";
1
+ import { i as INFRA_USER_AGENT, n as INFRA_API_URL, o as PLUGIN_VERSION, r as INFRA_KV_URL } from "./constants-C8_UJzzu.mjs";
2
+ import { a as createAPI, n as hash$1, o as createKV, r as hmacSha256Hex } from "./crypto-DRS7yhmR.mjs";
3
3
  import { EMAIL_TEMPLATES, createEmailSender, sendBulkEmails, sendEmail } from "./email.mjs";
4
4
  import { getCurrentAdapter, getCurrentAuthContext, getCurrentDBAdapterAsyncLocalStorage, runWithTransaction } from "@better-auth/core/context";
5
5
  import { APIError, generateId, getAuthTables, logger } from "better-auth";
@@ -21,14 +21,18 @@ function resolveConnectionOptions(options) {
21
21
  apiUrl: options?.apiUrl || INFRA_API_URL,
22
22
  kvUrl: options?.kvUrl || INFRA_KV_URL,
23
23
  apiKey: options?.apiKey || env.BETTER_AUTH_API_KEY || "",
24
- apiOptions: { timeout: options?.apiOptions?.timeout ?? options?.apiTimeout ?? 3e3 },
24
+ apiOptions: {
25
+ timeout: options?.apiOptions?.timeout ?? options?.apiTimeout ?? 3e3,
26
+ headers: options?.apiOptions?.headers
27
+ },
25
28
  kvOptions: {
26
29
  timeout: options?.kvOptions?.timeout ?? options?.kvTimeout ?? 1e3,
27
30
  retry: {
28
31
  attempts: options?.kvOptions?.retry?.attempts ?? 2,
29
32
  baseDelay: options?.kvOptions?.retry?.baseDelay ?? 400,
30
33
  maxDelay: options?.kvOptions?.retry?.maxDelay ?? 600
31
- }
34
+ },
35
+ headers: options?.kvOptions?.headers
32
36
  }
33
37
  };
34
38
  }
@@ -56,6 +60,21 @@ function resolveSentinelOptions(options) {
56
60
  };
57
61
  }
58
62
  //#endregion
63
+ //#region src/types.ts
64
+ /** Type-only cast — does not wrap or mutate ctx. */
65
+ function asInfraContext(ctx) {
66
+ return ctx;
67
+ }
68
+ /**
69
+ * better-auth createAuthMiddleware with InfraAuthContext on `ctx.context`.
70
+ * Pass-through at runtime — type-only (does not wrap the handler).
71
+ *
72
+ * Prefer this for dash/sentinel/identification hooks. Keep better-auth's
73
+ * createAuthMiddleware where middleware return values must extend AuthContext
74
+ * (e.g. JWT `payload` via `use: [...]`).
75
+ */
76
+ const createAuthMiddleware$1 = createAuthMiddleware;
77
+ //#endregion
59
78
  //#region ../utils/dist/ip.mjs
60
79
  /** Platform-set client IP headers (not accepted from clients on the open internet). */
61
80
  const DEFAULT_TRUSTED_IP_HEADERS = [
@@ -1102,7 +1121,7 @@ function shouldRunIdentification(ctx, getRoutes = IDENTIFICATION_GET_ROUTES) {
1102
1121
  * needs it; together they would append duplicate Set-Cookie headers).
1103
1122
  */
1104
1123
  function createIdentificationCookieAfterMiddleware() {
1105
- return createAuthMiddleware(async (ctx) => {
1124
+ return createAuthMiddleware$1(async (ctx) => {
1106
1125
  if (ctx.context.infraRidCookieSet) return;
1107
1126
  ctx.context.infraRidCookieSet = true;
1108
1127
  const headerRequestId = ctx.request?.headers.get("X-Request-Id");
@@ -1230,7 +1249,7 @@ function resolveUntrustedVisitorId(visitorId, ip, headerVisitorId) {
1230
1249
  */
1231
1250
  function createIdentificationMiddleware($kv, options) {
1232
1251
  const retry = options?.retry ?? DEFAULT_KV_RETRY;
1233
- return createAuthMiddleware(async (ctx) => {
1252
+ return createAuthMiddleware$1(async (ctx) => {
1234
1253
  const skipIdentification = options?.skipIdentification?.(ctx) ?? false;
1235
1254
  let headerVisitorId = null;
1236
1255
  let requestId = null;
@@ -1368,7 +1387,8 @@ function createSecurityClient(conn, $api, options, onSecurityEvent) {
1368
1387
  const resolvedApiUrl = conn.apiUrl || INFRA_API_URL;
1369
1388
  const emailSender = createEmailSender({
1370
1389
  apiUrl: resolvedApiUrl,
1371
- apiKey: conn.apiKey
1390
+ apiKey: conn.apiKey,
1391
+ apiOptions: { headers: conn.apiOptions.headers }
1372
1392
  });
1373
1393
  function logEvent(event) {
1374
1394
  const fullEvent = {
@@ -2475,7 +2495,8 @@ const sentinel = (options) => {
2475
2495
  const $kv = createKV({
2476
2496
  kvUrl: opts.kvUrl,
2477
2497
  apiKey: opts.apiKey,
2478
- timeout: opts.kvOptions.timeout
2498
+ timeout: opts.kvOptions.timeout,
2499
+ headers: opts.kvOptions.headers
2479
2500
  });
2480
2501
  const { tracker } = initTrackEvents($api);
2481
2502
  const { trackEvent } = tracker;
@@ -2582,8 +2603,9 @@ const sentinel = (options) => {
2582
2603
  databaseHooks: {
2583
2604
  user: {
2584
2605
  create: {
2585
- async before(user, ctx) {
2586
- if (!ctx) return;
2606
+ async before(user, _ctx) {
2607
+ if (!_ctx) return;
2608
+ const ctx = asInfraContext(_ctx);
2587
2609
  if (isDashRoute(ctx.path)) {
2588
2610
  if (user.email && typeof user.email === "string" && isEmailNormalizationEnabled(opts.security)) return { data: {
2589
2611
  ...user,
@@ -2617,8 +2639,9 @@ const sentinel = (options) => {
2617
2639
  email: normalizeEmail(user.email, ctx.context)
2618
2640
  } };
2619
2641
  },
2620
- async after(user, ctx) {
2621
- if (!ctx || isDashRoute(ctx.path)) return;
2642
+ async after(user, _ctx) {
2643
+ if (!_ctx || isDashRoute(_ctx.path)) return;
2644
+ const ctx = asInfraContext(_ctx);
2622
2645
  const visitorId = ctx.context.visitorId;
2623
2646
  const reservationId = ctx.context.freeTrialReservationId;
2624
2647
  if (visitorId && reservationId && opts.security?.freeTrialAbuse?.enabled) await ctx.context.runInBackgroundOrAwait(securityService.confirmFreeTrialSignup(visitorId, reservationId, user.id, ctx.context.requestId ?? null));
@@ -2633,8 +2656,9 @@ const sentinel = (options) => {
2633
2656
  } }
2634
2657
  },
2635
2658
  session: { create: {
2636
- async before(session, ctx) {
2637
- if (!ctx || isDashRoute(ctx.path)) return;
2659
+ async before(session, _ctx) {
2660
+ if (!_ctx || isDashRoute(_ctx.path)) return;
2661
+ const ctx = asInfraContext(_ctx);
2638
2662
  const visitorId = ctx.context.visitorId;
2639
2663
  const identification = ctx.context.identification;
2640
2664
  if (session.userId && identification?.location && visitorId) {
@@ -2666,8 +2690,9 @@ const sentinel = (options) => {
2666
2690
  }
2667
2691
  }
2668
2692
  },
2669
- async after(session, ctx) {
2670
- if (!ctx || !session.userId || isDashRoute(ctx.path)) return;
2693
+ async after(session, _ctx) {
2694
+ if (!_ctx || !session.userId || isDashRoute(_ctx.path)) return;
2695
+ const ctx = asInfraContext(_ctx);
2671
2696
  const visitorId = ctx.context.visitorId;
2672
2697
  const identification = ctx.context.identification;
2673
2698
  let user = null;
@@ -2699,7 +2724,7 @@ const sentinel = (options) => {
2699
2724
  ...phoneValidationHooks.before,
2700
2725
  {
2701
2726
  matcher: (ctx) => ctx.request?.method !== "GET" && !isDashRoute(ctx.path),
2702
- handler: createAuthMiddleware(async (ctx) => {
2727
+ handler: createAuthMiddleware$1(async (ctx) => {
2703
2728
  const visitorId = ctx.context.visitorId;
2704
2729
  const identification = ctx.context.identification;
2705
2730
  const ip = ctx.context.ip;
@@ -2759,7 +2784,7 @@ const sentinel = (options) => {
2759
2784
  },
2760
2785
  {
2761
2786
  matcher: (ctx) => !!opts.security?.staleUsers?.enabled && !isDashRoute(ctx.path),
2762
- handler: createAuthMiddleware(async (ctx) => {
2787
+ handler: createAuthMiddleware$1(async (ctx) => {
2763
2788
  if (ctx.context.returned instanceof Error) return;
2764
2789
  const created = ctx.context.newSession;
2765
2790
  const userId = created?.user?.id ?? created?.session?.userId;
@@ -2806,7 +2831,7 @@ const sentinel = (options) => {
2806
2831
  },
2807
2832
  {
2808
2833
  matcher: (ctx) => ctx.request?.method !== "GET" && !isDashRoute(ctx.path),
2809
- handler: createAuthMiddleware(async (ctx) => {
2834
+ handler: createAuthMiddleware$1(async (ctx) => {
2810
2835
  const untrustedVisitorId = ctx.context.untrustedVisitorId;
2811
2836
  const ip = ctx.context.ip;
2812
2837
  const body = ctx.body;
@@ -10525,11 +10550,12 @@ function createSMSSender(config) {
10525
10550
  if (!apiKey) logger.warn("[Dash] No API key provided for SMS sending. Set BETTER_AUTH_API_KEY environment variable or pass apiKey in config.");
10526
10551
  const $api = createFetch({
10527
10552
  baseURL: apiUrl,
10553
+ timeout: config?.apiOptions?.timeout ?? config?.apiTimeout ?? 3e3,
10528
10554
  headers: {
10555
+ ...config?.apiOptions?.headers,
10529
10556
  "user-agent": INFRA_USER_AGENT,
10530
10557
  Authorization: `Bearer ${apiKey}`
10531
- },
10532
- timeout: config?.apiOptions?.timeout ?? config?.apiTimeout ?? 3e3
10558
+ }
10533
10559
  });
10534
10560
  /**
10535
10561
  * Send an SMS with OTP code
@@ -10622,7 +10648,7 @@ function setPendingSessionTracking(ctx, pending) {
10622
10648
  }
10623
10649
  async function getRequestLocation() {
10624
10650
  try {
10625
- return (await getCurrentAuthContext()).context.location;
10651
+ return asInfraContext(await getCurrentAuthContext()).context.location;
10626
10652
  } catch {
10627
10653
  return;
10628
10654
  }
@@ -10638,7 +10664,8 @@ const dash = (options) => {
10638
10664
  const $kv = createKV({
10639
10665
  kvUrl: opts.kvUrl,
10640
10666
  apiKey: opts.apiKey,
10641
- timeout: opts.kvOptions.timeout
10667
+ timeout: opts.kvOptions.timeout,
10668
+ headers: opts.kvOptions.headers
10642
10669
  });
10643
10670
  const activityUpdateInterval = opts.activityTracking?.updateInterval ?? 3e5;
10644
10671
  const scheduleLastActiveUpdate = async (ctx, userId) => {
@@ -10970,7 +10997,8 @@ const dash = (options) => {
10970
10997
  const location = ctx.context.location;
10971
10998
  if (matchesAnyRoute(path, [routes.REQUEST_PASSWORD_RESET])) trackPasswordResetRequest(verification, trigger, ctx, location);
10972
10999
  } },
10973
- delete: { async after(verification, ctx) {
11000
+ delete: { async after(verification, _ctx) {
11001
+ const ctx = _ctx;
10974
11002
  if (!ctx) return;
10975
11003
  const path = ctx.path;
10976
11004
  const maybeUserId = ctx.context.session?.user.id ?? "unknown";
@@ -10994,7 +11022,7 @@ const dash = (options) => {
10994
11022
  after: [
10995
11023
  {
10996
11024
  matcher: (ctx) => !!getPendingSessionTracking(ctx),
10997
- handler: createAuthMiddleware(async (ctx) => {
11025
+ handler: createAuthMiddleware$1(async (ctx) => {
10998
11026
  const pending = getPendingSessionTracking(ctx);
10999
11027
  if (!pending) return;
11000
11028
  trackSessionLifecycle(pending.enrichedSession, pending.userId, ctx, pending.location, resolveUserFromContext(pending.userId, ctx), pending.trackSignIn, pending.impersonatedBy);
@@ -11009,8 +11037,7 @@ const dash = (options) => {
11009
11037
  routes.DASH_IMPERSONATE_USER
11010
11038
  ]);
11011
11039
  },
11012
- handler: createAuthMiddleware(async (_ctx) => {
11013
- const ctx = _ctx;
11040
+ handler: createAuthMiddleware$1(async (ctx) => {
11014
11041
  const maybeUserId = ctx.context.session?.user.id ?? "unknown";
11015
11042
  const trigger = getTriggerInfo(ctx, maybeUserId);
11016
11043
  if (matchesAnyRoute(ctx.path, [routes.SEND_VERIFICATION_EMAIL, routes.DASH_SEND_VERIFICATION_EMAIL]) && ctx.context.session && !(ctx.context.returned instanceof Error)) trackEmailVerificationSent(ctx.context.session.session, ctx.context.session.user, trigger, ctx.context.location);
@@ -11025,7 +11052,7 @@ const dash = (options) => {
11025
11052
  handler: createIdentificationCookieAfterMiddleware()
11026
11053
  },
11027
11054
  {
11028
- handler: createAuthMiddleware(async (ctx) => {
11055
+ handler: createAuthMiddleware$1(async (ctx) => {
11029
11056
  if (!opts.activityTracking?.enabled) return;
11030
11057
  if (activityUpdateInterval === 0) return;
11031
11058
  const session = ctx.context.session || ctx.context.newSession;
package/dist/native.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as DashGetAllAuditLogsInput, i as DashClientOptions, n as DashAuditLog, o as DashGetAuditLogsInput, r as DashAuditLogsResponse, s as dashClient, t as IdentifyClientOptions } from "./identify-client-options-Be9mAljS.mjs";
1
+ import { a as DashGetAllAuditLogsInput, i as DashClientOptions, n as DashAuditLog, o as DashGetAuditLogsInput, r as DashAuditLogsResponse, s as dashClient, t as IdentifyClientOptions } from "./identify-client-options-DgKA4Eq8.mjs";
2
2
  import { BetterAuthClientPlugin } from "better-auth";
3
3
  //#region src/sentinel/native/client.d.ts
4
4
  interface SentinelNativeClientOptions {
package/dist/native.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { o as createKV, t as bytesToHex } from "./crypto-C9Iqqv8l.mjs";
2
- import { a as resolveSentinelClientIdentifyUrl, c as identify, i as solvePoWChallenge, l as dashClient, n as decodePoWChallenge, o as resolveIdentifyClientRetry, r as encodePoWSolution, t as createPowRetryTimeout } from "./pow-retry-Bk5otjQT.mjs";
1
+ import { o as createKV, t as bytesToHex } from "./crypto-DRS7yhmR.mjs";
2
+ import { a as resolveSentinelClientIdentifyUrl, c as identify, i as solvePoWChallenge, l as dashClient, n as decodePoWChallenge, o as resolveIdentifyClientRetry, r as encodePoWSolution, t as createPowRetryTimeout } from "./pow-retry-Di0eUKbA.mjs";
3
3
  import { env } from "@better-auth/core/env";
4
4
  import { Dimensions, InteractionManager, PixelRatio, Platform } from "react-native";
5
5
  //#region src/sentinel/native/components.ts
@@ -1,4 +1,4 @@
1
- import { i as randomBytes, n as hash, t as bytesToHex } from "./crypto-C9Iqqv8l.mjs";
1
+ import { i as randomBytes, n as hash, t as bytesToHex } from "./crypto-DRS7yhmR.mjs";
2
2
  //#region src/dash-client.ts
3
3
  function resolveDashUserId(input, options) {
4
4
  return input.userId || options?.resolveUserId?.({
@@ -1,7 +1,8 @@
1
- import { BetterAuthPlugin, GenericEndpointContext } from "better-auth";
1
+ import { GenericEndpointContext } from "better-auth";
2
+ import { createAuthMiddleware } from "better-auth/api";
2
3
  import { createFetch } from "@better-fetch/fetch";
3
4
  import { BetterAuthRateLimitRule } from "@better-auth/core";
4
- import { APIError as APIError$1, Endpoint, EndpointOptions } from "better-call";
5
+ import { APIError as APIError$2, Endpoint, EndpointOptions } from "better-call";
5
6
  //#region src/identification.d.ts
6
7
  interface IPLocation {
7
8
  lat: number;
@@ -193,7 +194,7 @@ declare const sentinel: (options?: SentinelOptions) => {
193
194
  emailVerified: boolean;
194
195
  name: string;
195
196
  image?: string | null | undefined;
196
- } & Record<string, unknown>, ctx: import("better-auth").GenericEndpointContext | null): Promise<{
197
+ } & Record<string, unknown>, _ctx: import("better-auth").GenericEndpointContext | null): Promise<{
197
198
  data: {
198
199
  email: string;
199
200
  id: string;
@@ -212,7 +213,7 @@ declare const sentinel: (options?: SentinelOptions) => {
212
213
  emailVerified: boolean;
213
214
  name: string;
214
215
  image?: string | null | undefined;
215
- } & Record<string, unknown>, ctx: import("better-auth").GenericEndpointContext | null): Promise<void>;
216
+ } & Record<string, unknown>, _ctx: import("better-auth").GenericEndpointContext | null): Promise<void>;
216
217
  };
217
218
  update: {
218
219
  before(user: Partial<{
@@ -247,7 +248,7 @@ declare const sentinel: (options?: SentinelOptions) => {
247
248
  token: string;
248
249
  ipAddress?: string | null | undefined;
249
250
  userAgent?: string | null | undefined;
250
- } & Record<string, unknown>, ctx: import("better-auth").GenericEndpointContext | null): Promise<void>;
251
+ } & Record<string, unknown>, _ctx: import("better-auth").GenericEndpointContext | null): Promise<void>;
251
252
  after(session: {
252
253
  id: string;
253
254
  createdAt: Date;
@@ -257,7 +258,7 @@ declare const sentinel: (options?: SentinelOptions) => {
257
258
  token: string;
258
259
  ipAddress?: string | null | undefined;
259
260
  userAgent?: string | null | undefined;
260
- } & Record<string, unknown>, ctx: import("better-auth").GenericEndpointContext | null): Promise<void>;
261
+ } & Record<string, unknown>, _ctx: import("better-auth").GenericEndpointContext | null): Promise<void>;
261
262
  };
262
263
  };
263
264
  };
@@ -273,186 +274,13 @@ declare const sentinel: (options?: SentinelOptions) => {
273
274
  };
274
275
  };
275
276
  hooks: {
276
- before: ({
277
- matcher: (context: Pick<import("better-auth").HookEndpointContext, "path">) => boolean;
278
- handler: (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
279
- context: {
280
- method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
281
- path: string;
282
- body: any;
283
- query: Record<string, any> | undefined;
284
- params: Record<string, any> & string;
285
- request: Request | undefined;
286
- headers: Headers | undefined;
287
- setHeader: ((key: string, value: string) => void) & ((key: string, value: string) => void);
288
- setStatus: (status: import("better-call").Status) => void;
289
- getHeader: ((key: string) => string | null) & ((key: string) => string | null);
290
- getCookie: (key: string, prefix?: import("better-call").CookiePrefixOptions) => string | null;
291
- getSignedCookie: (key: string, secret: string, prefix?: import("better-call").CookiePrefixOptions) => Promise<string | null | false>;
292
- setCookie: (key: string, value: string, options?: import("better-call").CookieOptions) => string;
293
- setSignedCookie: (key: string, value: string, secret: string, options?: import("better-call").CookieOptions) => Promise<string>;
294
- responseHeaders: Headers;
295
- json: (<R extends Record<string, any> | null>(json: R, routerResponse?: {
296
- status?: number;
297
- headers?: Record<string, string>;
298
- response?: Response;
299
- body?: Record<string, string>;
300
- } | Response) => Promise<R>) & (<R extends Record<string, any> | null>(json: R, routerResponse?: {
301
- status?: number;
302
- headers?: Record<string, string>;
303
- response?: Response;
304
- } | Response) => Promise<R>);
305
- context: {
306
- [x: string]: any;
307
- } & {
308
- returned?: unknown | undefined;
309
- responseHeaders?: Headers | undefined;
310
- getPlugin: <ID extends import("better-auth").BetterAuthPluginRegistryIdentifier | import("better-auth").LiteralString, PluginOptions extends never>(pluginId: ID) => (ID extends keyof import("better-auth").BetterAuthPluginRegistry<unknown, unknown> ? import("better-auth").BetterAuthPluginRegistry<import("better-auth").BetterAuthOptions, PluginOptions>[ID] extends {
311
- creator: infer C;
312
- } ? C extends ((...args: any[]) => infer R) ? R : never : never : BetterAuthPlugin) | null;
313
- hasPlugin: <ID extends import("better-auth").BetterAuthPluginRegistryIdentifier | import("better-auth").LiteralString>(pluginId: ID) => ID extends never ? true : boolean;
314
- appName: string;
315
- baseURL: string;
316
- version: string;
317
- options: import("better-auth").BetterAuthOptions;
318
- trustedOrigins: string[];
319
- trustedProviders: string[];
320
- isTrustedOrigin: (url: string, settings?: {
321
- allowRelativePaths: boolean;
322
- }) => boolean;
323
- oauthConfig: {
324
- skipStateCookieCheck?: boolean | undefined;
325
- storeStateStrategy: "database" | "cookie";
326
- };
327
- newSession: {
328
- session: {
329
- id: string;
330
- createdAt: Date;
331
- updatedAt: Date;
332
- userId: string;
333
- expiresAt: Date;
334
- token: string;
335
- ipAddress?: string | null | undefined;
336
- userAgent?: string | null | undefined;
337
- } & Record<string, any>;
338
- user: {
339
- id: string;
340
- createdAt: Date;
341
- updatedAt: Date;
342
- email: string;
343
- emailVerified: boolean;
344
- name: string;
345
- image?: string | null | undefined;
346
- } & Record<string, any>;
347
- } | null;
348
- session: {
349
- session: {
350
- id: string;
351
- createdAt: Date;
352
- updatedAt: Date;
353
- userId: string;
354
- expiresAt: Date;
355
- token: string;
356
- ipAddress?: string | null | undefined;
357
- userAgent?: string | null | undefined;
358
- } & Record<string, any>;
359
- user: {
360
- id: string;
361
- createdAt: Date;
362
- updatedAt: Date;
363
- email: string;
364
- emailVerified: boolean;
365
- name: string;
366
- image?: string | null | undefined;
367
- } & Record<string, any>;
368
- } | null;
369
- setNewSession: (session: {
370
- session: {
371
- id: string;
372
- createdAt: Date;
373
- updatedAt: Date;
374
- userId: string;
375
- expiresAt: Date;
376
- token: string;
377
- ipAddress?: string | null | undefined;
378
- userAgent?: string | null | undefined;
379
- } & Record<string, any>;
380
- user: {
381
- id: string;
382
- createdAt: Date;
383
- updatedAt: Date;
384
- email: string;
385
- emailVerified: boolean;
386
- name: string;
387
- image?: string | null | undefined;
388
- } & Record<string, any>;
389
- } | null) => void;
390
- socialProviders: import("better-auth").OAuthProvider[];
391
- authCookies: import("better-auth").BetterAuthCookies;
392
- logger: ReturnType<(options?: import("better-auth").Logger | undefined) => import("better-auth").InternalLogger>;
393
- rateLimit: {
394
- enabled: boolean;
395
- window: number;
396
- max: number;
397
- storage: "memory" | "database" | "secondary-storage";
398
- } & Omit<import("better-auth").BetterAuthRateLimitOptions, "enabled" | "window" | "max" | "storage">;
399
- adapter: import("better-auth").DBAdapter<import("better-auth").BetterAuthOptions>;
400
- internalAdapter: import("better-auth").InternalAdapter<import("better-auth").BetterAuthOptions>;
401
- createAuthCookie: (cookieName: string, overrideAttributes?: Partial<import("better-call").CookieOptions> | undefined) => import("better-auth").BetterAuthCookie;
402
- secret: string;
403
- secretConfig: string | import("better-auth").SecretConfig;
404
- sessionConfig: {
405
- updateAge: number;
406
- expiresIn: number;
407
- freshAge: number;
408
- cookieRefreshCache: false | {
409
- enabled: true;
410
- updateAge: number;
411
- };
412
- };
413
- generateId: (options: {
414
- model: import("better-auth").ModelNames;
415
- size?: number | undefined;
416
- }) => string | false;
417
- secondaryStorage: import("better-auth").SecondaryStorage | undefined;
418
- password: {
419
- hash: (password: string) => Promise<string>;
420
- verify: (data: {
421
- password: string;
422
- hash: string;
423
- }) => Promise<boolean>;
424
- config: {
425
- minPasswordLength: number;
426
- maxPasswordLength: number;
427
- };
428
- checkPassword: (userId: string, ctx: import("better-auth").GenericEndpointContext<import("better-auth").BetterAuthOptions>) => Promise<boolean>;
429
- };
430
- tables: import("better-auth").BetterAuthDBSchema;
431
- runMigrations: () => Promise<void>;
432
- publishTelemetry: (event: {
433
- type: string;
434
- anonymousId?: string | undefined;
435
- payload: Record<string, any>;
436
- }) => Promise<void>;
437
- skipOriginCheck: boolean | string[];
438
- skipCSRFCheck: boolean;
439
- runInBackground: (promise: Promise<unknown>) => void;
440
- runInBackgroundOrAwait: (promise: Promise<unknown> | void) => import("better-auth").Awaitable<unknown>;
441
- };
442
- redirect: (url: string) => import("better-call").APIError;
443
- error: (status: ("OK" | "CREATED" | "ACCEPTED" | "NO_CONTENT" | "MULTIPLE_CHOICES" | "MOVED_PERMANENTLY" | "FOUND" | "SEE_OTHER" | "NOT_MODIFIED" | "TEMPORARY_REDIRECT" | "BAD_REQUEST" | "UNAUTHORIZED" | "PAYMENT_REQUIRED" | "FORBIDDEN" | "NOT_FOUND" | "METHOD_NOT_ALLOWED" | "NOT_ACCEPTABLE" | "PROXY_AUTHENTICATION_REQUIRED" | "REQUEST_TIMEOUT" | "CONFLICT" | "GONE" | "LENGTH_REQUIRED" | "PRECONDITION_FAILED" | "PAYLOAD_TOO_LARGE" | "URI_TOO_LONG" | "UNSUPPORTED_MEDIA_TYPE" | "RANGE_NOT_SATISFIABLE" | "EXPECTATION_FAILED" | "I'M_A_TEAPOT" | "MISDIRECTED_REQUEST" | "UNPROCESSABLE_ENTITY" | "LOCKED" | "FAILED_DEPENDENCY" | "TOO_EARLY" | "UPGRADE_REQUIRED" | "PRECONDITION_REQUIRED" | "TOO_MANY_REQUESTS" | "REQUEST_HEADER_FIELDS_TOO_LARGE" | "UNAVAILABLE_FOR_LEGAL_REASONS" | "INTERNAL_SERVER_ERROR" | "NOT_IMPLEMENTED" | "BAD_GATEWAY" | "SERVICE_UNAVAILABLE" | "GATEWAY_TIMEOUT" | "HTTP_VERSION_NOT_SUPPORTED" | "VARIANT_ALSO_NEGOTIATES" | "INSUFFICIENT_STORAGE" | "LOOP_DETECTED" | "NOT_EXTENDED" | "NETWORK_AUTHENTICATION_REQUIRED") | import("better-call").Status, body?: {
444
- message?: string;
445
- code?: string;
446
- } & Record<string, any>, headers?: HeadersInit) => import("better-call").APIError;
447
- };
448
- } | undefined>;
449
- } | {
450
- matcher: (ctx: import("better-auth").HookEndpointContext) => boolean;
451
- handler: (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<void>;
452
- })[];
277
+ before: {
278
+ matcher: (context: import("better-auth").HookEndpointContext) => boolean;
279
+ handler: import("better-auth/api").AuthMiddleware;
280
+ }[];
453
281
  after: {
454
282
  matcher: (ctx: import("better-auth").HookEndpointContext) => boolean;
455
- handler: (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<void>;
283
+ handler: import("better-call").Middleware<import("better-call").MiddlewareOptions, (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<unknown>>;
456
284
  }[];
457
285
  };
458
286
  };
@@ -491,11 +319,19 @@ interface ApiOptions {
491
319
  * @default 3000
492
320
  */
493
321
  timeout?: number;
322
+ /**
323
+ * Extra headers on every Dash API request.
324
+ * Cannot override built-in headers (`user-agent`, `x-api-key`).
325
+ */
326
+ headers?: Record<string, string>;
494
327
  }
495
328
  /**
496
329
  * Resolved {@link ApiOptions} with defaults applied.
497
330
  */
498
- type ApiOptionsResolved = Required<ApiOptions>;
331
+ type ApiOptionsResolved = {
332
+ timeout: number;
333
+ headers?: Record<string, string>;
334
+ };
499
335
  /**
500
336
  * KV HTTP client options.
501
337
  */
@@ -510,6 +346,11 @@ interface KvOptions {
510
346
  * @default { attempts: 2, baseDelay: 400, maxDelay: 600 }
511
347
  */
512
348
  retry?: KvRetryOptions;
349
+ /**
350
+ * Extra headers on every KV request.
351
+ * Cannot override built-in headers (`user-agent`, `x-api-key`).
352
+ */
353
+ headers?: Record<string, string>;
513
354
  }
514
355
  /**
515
356
  * Resolved {@link KvOptions} with defaults applied.
@@ -517,6 +358,7 @@ interface KvOptions {
517
358
  interface KvOptionsResolved {
518
359
  timeout: number;
519
360
  retry: KvRetryOptionsResolved;
361
+ headers?: Record<string, string>;
520
362
  }
521
363
  /**
522
364
  * Shared connection options used by infra plugins.
@@ -672,15 +514,44 @@ interface LocationData {
672
514
  }
673
515
  /** @deprecated Use LocationData instead */
674
516
  type LocationDataContext = LocationData;
675
- type InfraEndpointContext = (GenericEndpointContext & {
676
- context: {
677
- identification?: Identification | null | undefined;
678
- visitorId: string | null;
679
- requestId: string | null;
680
- ip: string | null;
681
- untrustedVisitorId: string | null;
682
- location: LocationData | undefined;
683
- };
684
- }) | undefined;
517
+ /**
518
+ * Plugin-attached AuthContext fields. better-auth types AuthContext as a fixed
519
+ * object; prefer {@link createAuthMiddleware} for hooks, {@link asInfraContext}
520
+ * for database hooks / getCurrentAuthContext.
521
+ */
522
+ type InfraAuthContext = GenericEndpointContext["context"] & {
523
+ identification?: Identification | null;
524
+ visitorId: string | null;
525
+ requestId: string | null;
526
+ ip: string | null;
527
+ untrustedVisitorId: string | null;
528
+ location: LocationData | undefined;
529
+ infraRidCookieSet?: boolean;
530
+ freeTrialReservationId?: string;
531
+ returned?: unknown;
532
+ payload?: unknown;
533
+ };
534
+ type InfraEndpointContextValue = Omit<GenericEndpointContext, "context"> & {
535
+ context: InfraAuthContext;
536
+ };
537
+ type InfraEndpointContext = InfraEndpointContextValue | undefined;
538
+ /** Type-only cast — does not wrap or mutate ctx. */
539
+ declare function asInfraContext<T extends {
540
+ context: object;
541
+ }>(ctx: T): Omit<T, "context"> & {
542
+ context: InfraAuthContext;
543
+ };
544
+ /**
545
+ * better-auth createAuthMiddleware with InfraAuthContext on `ctx.context`.
546
+ * Pass-through at runtime — type-only (does not wrap the handler).
547
+ *
548
+ * Prefer this for dash/sentinel/identification hooks. Keep better-auth's
549
+ * createAuthMiddleware where middleware return values must extend AuthContext
550
+ * (e.g. JWT `payload` via `use: [...]`).
551
+ */
552
+ declare const createAuthMiddleware$1: {
553
+ <R>(handler: (ctx: InfraEndpointContextValue) => R | Promise<R>): ReturnType<typeof createAuthMiddleware>;
554
+ <Options extends Record<string, unknown>, R>(options: Options, handler: (ctx: InfraEndpointContextValue) => R | Promise<R>): ReturnType<typeof createAuthMiddleware>;
555
+ };
685
556
  //#endregion
686
- export { ImpossibleTravelResult as C, SecurityVerdict as D, SecurityOptions as E, StaleUserResult as O, CredentialStuffingResult as S, SecurityEventType as T, LocationDataContext as _, DashOptionsInternal as a, sentinel as b, EndpointOptions as c, InfraPluginConnectionOptionsInternal as d, KvOptions as f, LocationData as g, KvRetryOptionsResolved as h, DashOptions as i, ThresholdConfig as k, InfraEndpointContext as l, KvRetryOptions as m, ApiOptions as n, DashOptionsResolved as o, KvOptionsResolved as p, ApiOptionsResolved as r, Endpoint as s, APIError$1 as t, InfraPluginConnectionOptions as u, SentinelOptions as v, SecurityEvent as w, CompromisedPasswordResult as x, SentinelOptionsInternal as y };
557
+ export { SecurityOptions as A, createAuthMiddleware$1 as C, ImpossibleTravelResult as D, CredentialStuffingResult as E, StaleUserResult as M, ThresholdConfig as N, SecurityEvent as O, asInfraContext as S, CompromisedPasswordResult as T, KvRetryOptionsResolved as _, DashOptionsInternal as a, SentinelOptions as b, EndpointOptions as c, InfraEndpointContextValue as d, InfraPluginConnectionOptions as f, KvRetryOptions as g, KvOptionsResolved as h, DashOptions as i, SecurityVerdict as j, SecurityEventType as k, InfraAuthContext as l, KvOptions as m, ApiOptions as n, DashOptionsResolved as o, InfraPluginConnectionOptionsInternal as p, ApiOptionsResolved as r, Endpoint as s, APIError$2 as t, InfraEndpointContext as u, LocationData as v, sentinel as w, SentinelOptionsInternal as x, LocationDataContext as y };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-auth/infra",
3
- "version": "0.4.7",
3
+ "version": "0.4.8",
4
4
  "description": "Dashboard and analytics plugin for Better Auth",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",
@@ -11,9 +11,9 @@
11
11
  "build": "bun --bun tsdown",
12
12
  "dev": "bun --bun tsdown --watch --no-clean",
13
13
  "typecheck": "tsc --noEmit",
14
- "test": "bun test --parallel",
15
- "test:watch": "bun test --watch",
16
- "coverage": "bun test --coverage --parallel"
14
+ "test": "vitest run",
15
+ "test:watch": "vitest",
16
+ "coverage": "vitest run --coverage"
17
17
  },
18
18
  "exports": {
19
19
  ".": {
@@ -66,19 +66,22 @@
66
66
  },
67
67
  "homepage": "https://better-auth.com",
68
68
  "devDependencies": {
69
- "@better-auth/kysely-adapter": "1.7.0-rc.1",
70
- "@better-auth/scim": "1.7.0-rc.1",
71
- "@better-auth/sso": "1.7.0-rc.1",
69
+ "@better-auth/kysely-adapter": "1.7.3",
70
+ "@better-auth/scim": "1.7.3",
71
+ "@better-auth/sso": "1.7.3",
72
72
  "@infra/mocks": "0.0.0",
73
73
  "@infra/utils": "0.0.0",
74
74
  "@types/bun": "latest",
75
75
  "@types/node": "^24.12.0",
76
- "better-auth": "1.7.0-rc.1",
76
+ "@vitest/browser-playwright": "5.0.0",
77
+ "@vitest/coverage-istanbul": "^5.0.0",
78
+ "better-auth": "1.7.3",
77
79
  "expo-crypto": "^57.0.1",
78
- "happy-dom": "^20.9.0",
79
80
  "msw": "^2.14.6",
81
+ "playwright": "^1.63.0",
80
82
  "tsdown": "^0.22.14",
81
83
  "typescript": "^6.0.3",
84
+ "vitest": "^5.0.0",
82
85
  "zod": "4.5.4"
83
86
  },
84
87
  "dependencies": {
@@ -86,7 +89,7 @@
86
89
  "@better-fetch/fetch": "1.3.1",
87
90
  "@noble/hashes": "^2.2.0",
88
91
  "@xmldom/xmldom": "^0.9.10",
89
- "better-call": "1.3.7",
92
+ "better-call": "1.4.0",
90
93
  "jose": "^6.2.10",
91
94
  "libphonenumber-js": "^1.13.11"
92
95
  },
@@ -116,5 +119,10 @@
116
119
  "expo-device": {
117
120
  "optional": true
118
121
  }
122
+ },
123
+ "msw": {
124
+ "workerDirectory": [
125
+ "public"
126
+ ]
119
127
  }
120
128
  }