@better-auth/infra 0.4.7 → 0.4.9

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.
@@ -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.9",
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
  }