@onmax/nuxt-better-auth 0.0.2-alpha.30 → 0.0.2-alpha.32

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 (51) hide show
  1. package/README.md +60 -17
  2. package/dist/module.d.mts +0 -9
  3. package/dist/module.json +2 -2
  4. package/dist/module.mjs +668 -267
  5. package/dist/runtime/app/components/BetterAuthState.d.vue.ts +4 -4
  6. package/dist/runtime/app/components/BetterAuthState.vue +1 -1
  7. package/dist/runtime/app/components/BetterAuthState.vue.d.ts +4 -4
  8. package/dist/runtime/app/composables/useAuthClient.d.ts +9 -0
  9. package/dist/runtime/app/composables/useAuthClient.js +34 -0
  10. package/dist/runtime/app/composables/useAuthClientAction.d.ts +1 -3
  11. package/dist/runtime/app/composables/useAuthClientAction.js +2 -2
  12. package/dist/runtime/app/composables/useAuthRequestFetch.d.ts +1 -1
  13. package/dist/runtime/app/composables/useSignIn.js +2 -2
  14. package/dist/runtime/app/composables/useSignUp.js +2 -2
  15. package/dist/runtime/app/composables/useUserSession.d.ts +5 -4
  16. package/dist/runtime/app/composables/useUserSession.js +91 -218
  17. package/dist/runtime/app/composables/useUserSessionState.d.ts +3 -0
  18. package/dist/runtime/app/composables/useUserSessionState.js +4 -0
  19. package/dist/runtime/app/internal/auth-action-error.js +1 -3
  20. package/dist/runtime/app/internal/auth-action-handles.js +1 -3
  21. package/dist/runtime/app/internal/redirect-helpers.d.ts +4 -0
  22. package/dist/runtime/app/internal/redirect-helpers.js +37 -0
  23. package/dist/runtime/app/internal/session-fetch.d.ts +12 -0
  24. package/dist/runtime/app/internal/session-fetch.js +56 -0
  25. package/dist/runtime/app/internal/utils.d.ts +1 -0
  26. package/dist/runtime/app/internal/utils.js +3 -0
  27. package/dist/runtime/app/internal/vue-safe-auth-proxy.d.ts +3 -0
  28. package/dist/runtime/app/internal/vue-safe-auth-proxy.js +68 -0
  29. package/dist/runtime/app/internal/wrap-auth-method.d.ts +15 -0
  30. package/dist/runtime/app/internal/wrap-auth-method.js +66 -0
  31. package/dist/runtime/app/middleware/auth.global.js +5 -4
  32. package/dist/runtime/app/plugins/session.client.js +2 -1
  33. package/dist/runtime/composables.d.ts +11 -0
  34. package/dist/runtime/composables.js +9 -0
  35. package/dist/runtime/config.d.ts +8 -6
  36. package/dist/runtime/config.js +3 -1
  37. package/dist/runtime/server/api/_better-auth/_schema.d.ts +1 -5
  38. package/dist/runtime/server/api/_better-auth/_schema.js +2 -1
  39. package/dist/runtime/server/api/_better-auth/accounts.get.d.ts +2 -2
  40. package/dist/runtime/server/api/_better-auth/config.get.js +1 -1
  41. package/dist/runtime/server/api/_better-auth/sessions.get.d.ts +2 -2
  42. package/dist/runtime/server/api/_better-auth/users.get.d.ts +2 -2
  43. package/dist/runtime/server/middleware/route-access.js +1 -1
  44. package/dist/runtime/server/utils/auth.d.ts +13 -2
  45. package/dist/runtime/server/utils/auth.js +42 -16
  46. package/dist/runtime/server/utils/session.d.ts +3 -1
  47. package/dist/runtime/server/utils/session.js +175 -1
  48. package/dist/runtime/server/virtual-modules.d.ts +5 -0
  49. package/dist/runtime/types/augment.d.ts +1 -3
  50. package/dist/runtime/types.d.ts +1 -1
  51. package/package.json +33 -26
@@ -0,0 +1,56 @@
1
+ import { useRequestFetch, useRequestHeaders } from "#imports";
2
+ import { normalizeAuthActionError } from "./auth-action-error.js";
3
+ export function stripToken(session) {
4
+ const { token: _, ...safe } = session;
5
+ return safe;
6
+ }
7
+ function isExpectedSignedOutSessionError(error) {
8
+ const normalizedError = normalizeAuthActionError(error);
9
+ if (normalizedError.status === 401)
10
+ return true;
11
+ return normalizedError.code === "UNAUTHORIZED";
12
+ }
13
+ export async function fetchSessionServer(session, user, authReady, options = {}) {
14
+ try {
15
+ const headers = options.headers || useRequestHeaders(["cookie"]);
16
+ const requestFetch = useRequestFetch();
17
+ const data = await requestFetch("/api/auth/get-session", { headers });
18
+ if (data?.session && data?.user) {
19
+ session.value = stripToken(data.session);
20
+ user.value = data.user;
21
+ } else {
22
+ session.value = null;
23
+ user.value = null;
24
+ }
25
+ } catch {
26
+ session.value = null;
27
+ user.value = null;
28
+ } finally {
29
+ if (!authReady.value)
30
+ authReady.value = true;
31
+ }
32
+ }
33
+ export async function fetchSessionClient(client, session, user, authReady, options = {}) {
34
+ try {
35
+ const headers = options.headers || useRequestHeaders(["cookie"]);
36
+ const fetchOptions = headers ? { headers } : void 0;
37
+ const query = options.force ? { disableCookieCache: true } : void 0;
38
+ const result = await client.getSession({ query }, fetchOptions);
39
+ const data = result.data;
40
+ if (data?.session && data?.user) {
41
+ session.value = stripToken(data.session);
42
+ user.value = data.user;
43
+ } else {
44
+ session.value = null;
45
+ user.value = null;
46
+ }
47
+ } catch (error) {
48
+ session.value = null;
49
+ user.value = null;
50
+ if (!isExpectedSignedOutSessionError(error))
51
+ console.error("[nuxt-better-auth] Failed to fetch session:", error);
52
+ } finally {
53
+ if (!authReady.value)
54
+ authReady.value = true;
55
+ }
56
+ }
@@ -0,0 +1 @@
1
+ export declare function isRecord(value: unknown): value is Record<string, unknown>;
@@ -0,0 +1,3 @@
1
+ export function isRecord(value) {
2
+ return Boolean(value && typeof value === "object");
3
+ }
@@ -0,0 +1,3 @@
1
+ export declare function isAuthProxyProbeKey(prop: PropertyKey): boolean;
2
+ export declare function createVueSafeAuthFacade<T extends object>(resolve: (prop: PropertyKey, receiver: object) => unknown): T;
3
+ export declare function createVueSafeAuthProxy<T>(target: T): T;
@@ -0,0 +1,68 @@
1
+ const promiseProbeKeys = /* @__PURE__ */ new Set(["then", "catch", "finally"]);
2
+ export function isAuthProxyProbeKey(prop) {
3
+ return typeof prop !== "string" || promiseProbeKeys.has(prop) || prop.startsWith("__v");
4
+ }
5
+ function isObjectLike(value) {
6
+ return typeof value === "object" && value !== null || typeof value === "function";
7
+ }
8
+ export function createVueSafeAuthFacade(resolve) {
9
+ const propertyCache = /* @__PURE__ */ new Map();
10
+ const facadeTarget = {};
11
+ Object.defineProperty(facadeTarget, "__v_skip", {
12
+ value: true,
13
+ configurable: true
14
+ });
15
+ return new Proxy(facadeTarget, {
16
+ get(_target, prop, receiver) {
17
+ if (prop === "__v_skip")
18
+ return true;
19
+ if (isAuthProxyProbeKey(prop))
20
+ return void 0;
21
+ if (propertyCache.has(prop))
22
+ return propertyCache.get(prop);
23
+ const value = resolve(prop, receiver);
24
+ propertyCache.set(prop, value);
25
+ return value;
26
+ }
27
+ });
28
+ }
29
+ export function createVueSafeAuthProxy(target) {
30
+ if (!isObjectLike(target))
31
+ return target;
32
+ const cache = /* @__PURE__ */ new WeakMap();
33
+ const wrap = (value) => {
34
+ if (!isObjectLike(value))
35
+ return value;
36
+ const cached = cache.get(value);
37
+ if (cached)
38
+ return cached;
39
+ const propertyCache = /* @__PURE__ */ new Map();
40
+ const handler = {
41
+ get(target2, prop, receiver) {
42
+ if (prop === "__v_skip")
43
+ return true;
44
+ if (isAuthProxyProbeKey(prop))
45
+ return void 0;
46
+ if (propertyCache.has(prop))
47
+ return propertyCache.get(prop);
48
+ const wrapped = wrap(Reflect.get(target2, prop, receiver));
49
+ propertyCache.set(prop, wrapped);
50
+ return wrapped;
51
+ }
52
+ };
53
+ if (typeof value === "function") {
54
+ handler.apply = (target2, thisArg, args) => Reflect.apply(target2, thisArg, args);
55
+ }
56
+ const proxy = new Proxy(value, handler);
57
+ cache.set(value, proxy);
58
+ return proxy;
59
+ };
60
+ const createRootFacade = (value) => {
61
+ if (!isObjectLike(value))
62
+ return value;
63
+ const proxy = createVueSafeAuthFacade((prop, receiver) => wrap(Reflect.get(value, prop, receiver)));
64
+ cache.set(value, proxy);
65
+ return proxy;
66
+ };
67
+ return createRootFacade(target);
68
+ }
@@ -0,0 +1,15 @@
1
+ import type { ComputedRef } from 'vue';
2
+ export declare function wrapOnSuccess(fetchSession: (options?: {
3
+ force?: boolean;
4
+ }) => Promise<void>, loggedIn: ComputedRef<boolean>, waitForSession: () => Promise<void>, cb: (ctx: unknown) => void | Promise<void>): (ctx: unknown) => Promise<void>;
5
+ export declare function wrapAuthMethod<T extends (...args: unknown[]) => Promise<unknown>>(method: T, deps: {
6
+ fetchSession: (options?: {
7
+ force?: boolean;
8
+ }) => Promise<void>;
9
+ loggedIn: ComputedRef<boolean>;
10
+ waitForSession: () => Promise<void>;
11
+ resolvePostAuthSuccessRedirect: () => (() => Promise<void>) | undefined;
12
+ }, wrapOptions?: {
13
+ shouldSkipSessionSync?: (data: unknown, options: unknown) => boolean;
14
+ transformData?: (data: unknown, options: unknown) => unknown;
15
+ }): T;
@@ -0,0 +1,66 @@
1
+ import { nextTick } from "#imports";
2
+ import { isRecord } from "./utils.js";
3
+ export function wrapOnSuccess(fetchSession, loggedIn, waitForSession, cb) {
4
+ return async (ctx) => {
5
+ await fetchSession({ force: true });
6
+ if (!loggedIn.value)
7
+ await waitForSession();
8
+ await nextTick();
9
+ await cb(ctx);
10
+ };
11
+ }
12
+ export function wrapAuthMethod(method, deps, wrapOptions = {}) {
13
+ return (async (...args) => {
14
+ const originalData = args[0];
15
+ const options = args[1];
16
+ const data = wrapOptions.transformData?.(originalData, options) ?? originalData;
17
+ const dataRecord = isRecord(data) ? data : void 0;
18
+ const optionsRecord = isRecord(options) ? options : void 0;
19
+ if (wrapOptions.shouldSkipSessionSync?.(data, options))
20
+ return method(data, options);
21
+ const fetchOptions = isRecord(dataRecord?.fetchOptions) ? dataRecord.fetchOptions : void 0;
22
+ const nestedOnSuccess = fetchOptions?.onSuccess;
23
+ const topLevelOnSuccess = optionsRecord?.onSuccess;
24
+ const fallbackOnSuccess = deps.resolvePostAuthSuccessRedirect();
25
+ const wrappedFallbackOnSuccess = fallbackOnSuccess && wrapOnSuccess(deps.fetchSession, deps.loggedIn, deps.waitForSession, async () => {
26
+ if (!deps.loggedIn.value)
27
+ return;
28
+ await fallbackOnSuccess();
29
+ });
30
+ if (typeof nestedOnSuccess === "function") {
31
+ const nextData = {
32
+ ...dataRecord,
33
+ fetchOptions: {
34
+ ...fetchOptions,
35
+ onSuccess: wrapOnSuccess(deps.fetchSession, deps.loggedIn, deps.waitForSession, nestedOnSuccess)
36
+ }
37
+ };
38
+ return method(nextData, options);
39
+ }
40
+ if (typeof topLevelOnSuccess === "function") {
41
+ const nextOptions = {
42
+ ...optionsRecord,
43
+ onSuccess: wrapOnSuccess(deps.fetchSession, deps.loggedIn, deps.waitForSession, topLevelOnSuccess)
44
+ };
45
+ return method(data, nextOptions);
46
+ }
47
+ if (wrappedFallbackOnSuccess) {
48
+ if (fetchOptions) {
49
+ const nextData = {
50
+ ...dataRecord,
51
+ fetchOptions: {
52
+ ...fetchOptions,
53
+ onSuccess: wrappedFallbackOnSuccess
54
+ }
55
+ };
56
+ return method(nextData, options);
57
+ }
58
+ const nextOptions = {
59
+ ...optionsRecord,
60
+ onSuccess: wrappedFallbackOnSuccess
61
+ };
62
+ return method(data, nextOptions);
63
+ }
64
+ return method(data, options);
65
+ });
66
+ }
@@ -1,7 +1,8 @@
1
- import { createError, defineNuxtRouteMiddleware, getRouteRules, navigateTo, useNuxtApp, useRequestHeaders, useRuntimeConfig, useUserSession } from "#imports";
2
1
  import { defu } from "defu";
3
2
  import { createRouter, toRouteMatcher } from "radix3";
3
+ import { createError, defineNuxtRouteMiddleware, getRouteRules, navigateTo, useNuxtApp, useRequestHeaders, useRuntimeConfig } from "#imports";
4
4
  import { matchesUser } from "../../utils/match-user.js";
5
+ import { useUserSession } from "../composables/useUserSession.js";
5
6
  let authRouteRulesPromise = null;
6
7
  let routeRulesMatcherPromise = null;
7
8
  export default defineNuxtRouteMiddleware(async (to) => {
@@ -25,13 +26,13 @@ export default defineNuxtRouteMiddleware(async (to) => {
25
26
  return;
26
27
  const config = useRuntimeConfig().public.auth;
27
28
  const { fetchSession, user, loggedIn } = useUserSession();
28
- if (!loggedIn.value) {
29
+ const mode = typeof auth === "string" ? auth : auth?.only ?? "user";
30
+ const redirectTo = typeof auth === "object" ? auth.redirectTo : void 0;
31
+ if (!loggedIn.value || mode === "guest") {
29
32
  const headers = import.meta.server ? useRequestHeaders(["cookie"]) : void 0;
30
33
  const isHydratedPrerenderPayload = (import.meta.client || !import.meta.server) && nuxtApp.isHydrating && Boolean(nuxtApp.payload.prerenderedAt || nuxtApp.payload.isCached);
31
34
  await fetchSession({ headers, ...isHydratedPrerenderPayload ? { force: true } : {} });
32
35
  }
33
- const mode = typeof auth === "string" ? auth : auth?.only ?? "user";
34
- const redirectTo = typeof auth === "object" ? auth.redirectTo : void 0;
35
36
  if (mode === "guest") {
36
37
  if (loggedIn.value)
37
38
  return navigateTo(redirectTo ?? config?.redirects?.guest ?? "/");
@@ -1,4 +1,5 @@
1
- import { defineNuxtPlugin, useUserSession } from "#imports";
1
+ import { defineNuxtPlugin } from "#imports";
2
+ import { useUserSession } from "../composables/useUserSession.js";
2
3
  export default defineNuxtPlugin(async (nuxtApp) => {
3
4
  const { fetchSession } = useUserSession();
4
5
  const safeFetch = async () => {
@@ -0,0 +1,11 @@
1
+ export { useAction } from './app/composables/useAction.js';
2
+ export { useAuthAsyncData } from './app/composables/useAuthAsyncData.js';
3
+ export { useAuthClient } from './app/composables/useAuthClient.js';
4
+ export { useAuthClientAction } from './app/composables/useAuthClientAction.js';
5
+ export { useAuthRequestFetch } from './app/composables/useAuthRequestFetch.js';
6
+ export { useSignIn } from './app/composables/useSignIn.js';
7
+ export { useSignUp } from './app/composables/useSignUp.js';
8
+ export { useUserSession } from './app/composables/useUserSession.js';
9
+ export type { SignOutOptions, UseUserSessionReturn } from './app/composables/useUserSession.js';
10
+ export { useUserSessionState } from './app/composables/useUserSessionState.js';
11
+ export type { UseUserSessionStateReturn } from './app/composables/useUserSessionState.js';
@@ -0,0 +1,9 @@
1
+ export { useAction } from "./app/composables/useAction.js";
2
+ export { useAuthAsyncData } from "./app/composables/useAuthAsyncData.js";
3
+ export { useAuthClient } from "./app/composables/useAuthClient.js";
4
+ export { useAuthClientAction } from "./app/composables/useAuthClientAction.js";
5
+ export { useAuthRequestFetch } from "./app/composables/useAuthRequestFetch.js";
6
+ export { useSignIn } from "./app/composables/useSignIn.js";
7
+ export { useSignUp } from "./app/composables/useSignUp.js";
8
+ export { useUserSession } from "./app/composables/useUserSession.js";
9
+ export { useUserSessionState } from "./app/composables/useUserSessionState.js";
@@ -1,9 +1,11 @@
1
1
  import type { BetterAuthOptions, BetterAuthPlugin } from 'better-auth';
2
2
  import type { BetterAuthClientOptions } from 'better-auth/client';
3
- import type { CasingOption } from '../schema-generator.js';
4
- import type { ServerAuthContext } from './types/augment.js';
3
+ import type { Casing } from 'drizzle-orm/utils';
4
+ import type { ServerAuthContext as BaseServerAuthContext } from './types/augment.js';
5
5
  import { createAuthClient } from 'better-auth/vue';
6
- export type { ServerAuthContext };
6
+ export interface ServerAuthContextExtension {
7
+ }
8
+ export type ServerAuthContext = BaseServerAuthContext & ServerAuthContextExtension;
7
9
  export interface ClientAuthContext {
8
10
  siteUrl: string;
9
11
  }
@@ -20,9 +22,9 @@ export type EffectiveDatabaseProviderId = 'user' | ModuleDatabaseProviderId;
20
22
  export interface BetterAuthModuleOptions {
21
23
  /** Client-only mode - skip server setup for external auth backends */
22
24
  clientOnly?: boolean;
23
- /** Server config path relative to rootDir. Default: 'server/auth.config' */
25
+ /** Server config path. Relative paths resolve from the layer that declares them. Default: 'server/auth.config' */
24
26
  serverConfig?: string;
25
- /** Client config path relative to rootDir. Default: 'app/auth.config' */
27
+ /** Client config path. Relative paths resolve from the layer that declares them. Default: 'app/auth.config' */
26
28
  clientConfig?: string;
27
29
  redirects?: {
28
30
  /** Where to redirect unauthenticated users. Default: '/login' */
@@ -69,7 +71,7 @@ export interface BetterAuthModuleOptions {
69
71
  /** Plural table names: user → users. Default: false */
70
72
  usePlural?: boolean;
71
73
  /** Column/table name casing. Explicit value takes precedence over hub.db.casing. */
72
- casing?: CasingOption;
74
+ casing?: Casing;
73
75
  };
74
76
  }
75
77
  export interface AuthRuntimeConfig {
@@ -6,6 +6,8 @@ export function defineClientAuth(config) {
6
6
  return (baseURL) => {
7
7
  const ctx = { siteUrl: baseURL };
8
8
  const resolved = typeof config === "function" ? config(ctx) : config;
9
- return createAuthClient({ ...resolved, baseURL });
9
+ const { baseURL: configuredBaseURL, ...resolvedOptions } = resolved;
10
+ const clientOptions = { ...resolvedOptions, baseURL: configuredBaseURL ?? baseURL };
11
+ return createAuthClient(clientOptions);
10
12
  };
11
13
  }
@@ -1,8 +1,4 @@
1
1
  import { z } from 'zod';
2
- export declare const paginationQuerySchema: z.ZodObject<{
3
- page: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
4
- limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
5
- search: z.ZodDefault<z.ZodString>;
6
- }, z.core.$strip>;
2
+ export declare const paginationQuerySchema: any;
7
3
  export type PaginationQuery = z.infer<typeof paginationQuerySchema>;
8
4
  export declare function sanitizeSearchPattern(search: string): string;
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ const SQL_LIKE_ESCAPE_RE = /[%_\\]/g;
2
3
  export const paginationQuerySchema = z.object({
3
4
  page: z.coerce.number().int().min(1).default(1),
4
5
  limit: z.coerce.number().int().min(1).max(100).default(20),
@@ -7,5 +8,5 @@ export const paginationQuerySchema = z.object({
7
8
  export function sanitizeSearchPattern(search) {
8
9
  if (!search)
9
10
  return "";
10
- return `%${search.replace(/[%_\\]/g, "\\$&")}%`;
11
+ return `%${search.replace(SQL_LIKE_ESCAPE_RE, "\\$&")}%`;
11
12
  }
@@ -7,8 +7,8 @@ declare const _default: import("h3").EventHandler<import("h3").EventHandlerReque
7
7
  } | {
8
8
  accounts: any;
9
9
  total: any;
10
- page: number;
11
- limit: number;
10
+ page: any;
11
+ limit: any;
12
12
  error?: undefined;
13
13
  }>>;
14
14
  export default _default;
@@ -1,5 +1,5 @@
1
1
  import { defineEventHandler } from "h3";
2
- import { useRuntimeConfig } from "nitropack/runtime";
2
+ import { useRuntimeConfig } from "#imports";
3
3
  import { serverAuth } from "../../utils/auth.js";
4
4
  export default defineEventHandler(async (event) => {
5
5
  try {
@@ -9,8 +9,8 @@ declare const _default: import("h3").EventHandler<import("h3").EventHandlerReque
9
9
  } | {
10
10
  sessions: SafeSession[];
11
11
  total: any;
12
- page: number;
13
- limit: number;
12
+ page: any;
13
+ limit: any;
14
14
  error?: undefined;
15
15
  }>>;
16
16
  export default _default;
@@ -7,8 +7,8 @@ declare const _default: import("h3").EventHandler<import("h3").EventHandlerReque
7
7
  } | {
8
8
  users: any;
9
9
  total: any;
10
- page: number;
11
- limit: number;
10
+ page: any;
11
+ limit: any;
12
12
  error?: undefined;
13
13
  }>>;
14
14
  export default _default;
@@ -1,5 +1,5 @@
1
1
  import { createError, defineEventHandler, getRequestURL } from "h3";
2
- import { getRouteRules } from "nitropack/runtime";
2
+ import { getRouteRules } from "#imports";
3
3
  import { matchesUser } from "../../utils/match-user.js";
4
4
  import { getUserSession, requireUserSession } from "../utils/session.js";
5
5
  export default defineEventHandler(async (event) => {
@@ -1,8 +1,19 @@
1
+ import type { BetterAuthOptions } from 'better-auth';
1
2
  import type { H3Event } from 'h3';
2
- import createServerAuth from '#auth/server';
3
3
  import { betterAuth } from 'better-auth';
4
+ import createServerAuth from '#auth/server';
4
5
  type AuthOptions = ReturnType<typeof createServerAuth>;
5
- type AuthInstance = ReturnType<typeof betterAuth<AuthOptions>>;
6
+ type UserAuthConfig = AuthOptions & {
7
+ trustedOrigins?: BetterAuthOptions['trustedOrigins'];
8
+ secondaryStorage?: BetterAuthOptions['secondaryStorage'];
9
+ };
10
+ type ResolvedAuthOptions = UserAuthConfig & {
11
+ secret: string;
12
+ baseURL: string;
13
+ trustedOrigins?: BetterAuthOptions['trustedOrigins'];
14
+ database?: BetterAuthOptions['database'];
15
+ };
16
+ type AuthInstance = ReturnType<typeof betterAuth<ResolvedAuthOptions>>;
6
17
  /** Returns Better Auth instance. Caches per resolved host (or single instance when siteUrl is explicit). */
7
18
  export declare function serverAuth(event?: H3Event): AuthInstance;
8
19
  export {};
@@ -1,14 +1,27 @@
1
- import { createDatabase, db } from "#auth/database";
2
- import { createSecondaryStorage } from "#auth/secondary-storage";
3
- import createServerAuth from "#auth/server";
4
1
  import { betterAuth } from "better-auth";
5
2
  import { getRequestHost, getRequestProtocol } from "h3";
6
3
  import { useRuntimeConfig } from "nitropack/runtime";
7
4
  import { withoutProtocol } from "ufo";
5
+ import { createDatabase, db } from "#auth/database";
6
+ import { createSecondaryStorage } from "#auth/secondary-storage";
7
+ import createServerAuth from "#auth/server";
8
8
  import { resolveCustomSecondaryStorageRequirement } from "./custom-secondary-storage.js";
9
9
  const _authCache = /* @__PURE__ */ new Map();
10
+ const requestAuthKey = Symbol.for("nuxt-better-auth.requestAuth");
10
11
  let _baseURLInferenceLogged = false;
11
12
  let _customSecondaryStorageMisconfigWarned = false;
13
+ const fallbackRequestAuthContext = /* @__PURE__ */ new WeakMap();
14
+ function getRequestAuthContext(event) {
15
+ const eventWithContext = event;
16
+ if (eventWithContext.context && typeof eventWithContext.context === "object")
17
+ return eventWithContext.context;
18
+ let context = fallbackRequestAuthContext.get(event);
19
+ if (!context) {
20
+ context = {};
21
+ fallbackRequestAuthContext.set(event, context);
22
+ }
23
+ return context;
24
+ }
12
25
  function normalizeLoopbackOrigin(origin) {
13
26
  if (!import.meta.dev)
14
27
  return origin;
@@ -155,8 +168,8 @@ function getRequestOrigin(request) {
155
168
  return void 0;
156
169
  }
157
170
  }
158
- function withDevTrustedOrigins(trustedOrigins, hasExplicitSiteUrl) {
159
- if (!import.meta.dev || !hasExplicitSiteUrl)
171
+ function withDevTrustedOrigins(trustedOrigins) {
172
+ if (!import.meta.dev)
160
173
  return trustedOrigins;
161
174
  const devOrigins = getDevTrustedOrigins();
162
175
  const mergeOrigins = (origins, request) => {
@@ -183,14 +196,15 @@ function withDevTrustedOrigins(trustedOrigins, hasExplicitSiteUrl) {
183
196
  export function serverAuth(event) {
184
197
  const runtimeConfig = useRuntimeConfig();
185
198
  const siteUrl = getBaseURL(event);
199
+ const requestOrigin = resolveEventOrigin(event);
186
200
  const hasExplicitSiteUrl = runtimeConfig.public.siteUrl && typeof runtimeConfig.public.siteUrl === "string";
187
201
  const cacheKey = hasExplicitSiteUrl ? "__explicit__" : siteUrl;
188
- const cached = _authCache.get(cacheKey);
189
- if (cached)
190
- return cached;
191
- const database = createDatabase();
192
- const userConfig = createServerAuth({ runtimeConfig, db });
193
- const trustedOrigins = withDevTrustedOrigins(userConfig.trustedOrigins, Boolean(hasExplicitSiteUrl));
202
+ const requestContext = event ? getRequestAuthContext(event) : void 0;
203
+ if (requestContext?.[requestAuthKey])
204
+ return requestContext[requestAuthKey];
205
+ const database = createDatabase(event);
206
+ const userConfig = createServerAuth({ runtimeConfig, db, requestOrigin });
207
+ const trustedOrigins = withDevTrustedOrigins(userConfig.trustedOrigins);
194
208
  const hubSecondaryStorage = runtimeConfig.auth?.hubSecondaryStorage;
195
209
  const customSecondaryStorage = resolveCustomSecondaryStorageRequirement(hubSecondaryStorage, userConfig.secondaryStorage != null, Boolean(import.meta.dev));
196
210
  if (customSecondaryStorage?.shouldThrow)
@@ -199,14 +213,26 @@ export function serverAuth(event) {
199
213
  _customSecondaryStorageMisconfigWarned = true;
200
214
  console.warn(customSecondaryStorage.message);
201
215
  }
202
- const auth = betterAuth({
216
+ if (!database) {
217
+ const cached = _authCache.get(cacheKey);
218
+ if (cached) {
219
+ if (requestContext)
220
+ requestContext[requestAuthKey] = cached;
221
+ return cached;
222
+ }
223
+ }
224
+ const authOptions = {
203
225
  ...userConfig,
204
- ...database && { database },
205
- ...hubSecondaryStorage === true && { secondaryStorage: createSecondaryStorage() },
226
+ ...database ? { database } : {},
227
+ ...hubSecondaryStorage === true ? { secondaryStorage: createSecondaryStorage() } : {},
206
228
  secret: runtimeConfig.betterAuthSecret,
207
229
  baseURL: siteUrl,
208
230
  trustedOrigins
209
- });
210
- _authCache.set(cacheKey, auth);
231
+ };
232
+ const auth = betterAuth(authOptions);
233
+ if (requestContext)
234
+ requestContext[requestAuthKey] = auth;
235
+ if (!database)
236
+ _authCache.set(cacheKey, auth);
211
237
  return auth;
212
238
  }
@@ -1,5 +1,7 @@
1
- import type { AppSession, RequireSessionOptions } from '#nuxt-better-auth';
2
1
  import type { H3Event } from 'h3';
2
+ import type { AppSession, AuthSession, RequireSessionOptions } from '#nuxt-better-auth';
3
3
  export declare function getRequestSession(event: H3Event): Promise<AppSession | null>;
4
4
  export declare function getUserSession(event: H3Event): Promise<AppSession | null>;
5
+ export declare function setSessionCookie(event: H3Event, token: string): Promise<void>;
6
+ export declare function createSession(event: H3Event, userId: string): Promise<AuthSession>;
5
7
  export declare function requireUserSession(event: H3Event, options?: RequireSessionOptions): Promise<AppSession>;