@onmax/nuxt-better-auth 0.0.2-alpha.8 → 0.0.2

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 (70) hide show
  1. package/README.md +57 -17
  2. package/dist/module.d.mts +28 -1
  3. package/dist/module.json +3 -3
  4. package/dist/module.mjs +1272 -339
  5. package/dist/runtime/app/components/BetterAuthState.d.vue.ts +4 -4
  6. package/dist/runtime/app/components/BetterAuthState.vue +1 -0
  7. package/dist/runtime/app/components/BetterAuthState.vue.d.ts +4 -4
  8. package/dist/runtime/app/composables/useAction.d.ts +2 -0
  9. package/dist/runtime/app/composables/useAction.js +6 -0
  10. package/dist/runtime/app/composables/useAuthAsyncData.d.ts +6 -0
  11. package/dist/runtime/app/composables/useAuthAsyncData.js +16 -0
  12. package/dist/runtime/app/composables/useAuthClient.d.ts +9 -0
  13. package/dist/runtime/app/composables/useAuthClient.js +34 -0
  14. package/dist/runtime/app/composables/useAuthClientAction.d.ts +3 -0
  15. package/dist/runtime/app/composables/useAuthClientAction.js +15 -0
  16. package/dist/runtime/app/composables/useAuthRequestFetch.d.ts +11 -0
  17. package/dist/runtime/app/composables/useAuthRequestFetch.js +4 -0
  18. package/dist/runtime/app/composables/useSignIn.d.ts +16 -0
  19. package/dist/runtime/app/composables/useSignIn.js +8 -0
  20. package/dist/runtime/app/composables/useSignUp.d.ts +5 -0
  21. package/dist/runtime/app/composables/useSignUp.js +8 -0
  22. package/dist/runtime/app/composables/useUserSession.d.ts +6 -5
  23. package/dist/runtime/app/composables/useUserSession.js +189 -100
  24. package/dist/runtime/app/composables/useUserSessionState.d.ts +3 -0
  25. package/dist/runtime/app/composables/useUserSessionState.js +4 -0
  26. package/dist/runtime/app/internal/auth-action-error.d.ts +3 -0
  27. package/dist/runtime/app/internal/auth-action-error.js +33 -0
  28. package/dist/runtime/app/internal/auth-action-handles.d.ts +18 -0
  29. package/dist/runtime/app/internal/auth-action-handles.js +105 -0
  30. package/dist/runtime/app/internal/redirect-helpers.d.ts +4 -0
  31. package/dist/runtime/app/internal/redirect-helpers.js +37 -0
  32. package/dist/runtime/app/internal/session-fetch.d.ts +12 -0
  33. package/dist/runtime/app/internal/session-fetch.js +56 -0
  34. package/dist/runtime/app/internal/utils.d.ts +1 -0
  35. package/dist/runtime/app/internal/utils.js +3 -0
  36. package/dist/runtime/app/internal/vue-safe-auth-proxy.d.ts +3 -0
  37. package/dist/runtime/app/internal/vue-safe-auth-proxy.js +68 -0
  38. package/dist/runtime/app/internal/wrap-auth-method.d.ts +15 -0
  39. package/dist/runtime/app/internal/wrap-auth-method.js +66 -0
  40. package/dist/runtime/app/middleware/auth.global.js +77 -15
  41. package/dist/runtime/app/pages/__better-auth-devtools.vue +4 -10
  42. package/dist/runtime/composables.d.ts +11 -0
  43. package/dist/runtime/composables.js +9 -0
  44. package/dist/runtime/config.d.ts +69 -15
  45. package/dist/runtime/config.js +9 -2
  46. package/dist/runtime/server/api/_better-auth/_schema.d.ts +1 -5
  47. package/dist/runtime/server/api/_better-auth/_schema.js +2 -1
  48. package/dist/runtime/server/api/_better-auth/accounts.get.d.ts +2 -2
  49. package/dist/runtime/server/api/_better-auth/accounts.get.js +3 -2
  50. package/dist/runtime/server/api/_better-auth/config.get.d.ts +9 -3
  51. package/dist/runtime/server/api/_better-auth/config.get.js +18 -6
  52. package/dist/runtime/server/api/_better-auth/sessions.delete.js +3 -2
  53. package/dist/runtime/server/api/_better-auth/sessions.get.d.ts +5 -3
  54. package/dist/runtime/server/api/_better-auth/sessions.get.js +3 -2
  55. package/dist/runtime/server/api/_better-auth/users.get.d.ts +2 -2
  56. package/dist/runtime/server/api/_better-auth/users.get.js +3 -2
  57. package/dist/runtime/server/api/auth/[...all].js +1 -1
  58. package/dist/runtime/server/middleware/route-access.js +2 -1
  59. package/dist/runtime/server/tsconfig.json +9 -1
  60. package/dist/runtime/server/utils/auth.d.ts +16 -8
  61. package/dist/runtime/server/utils/auth.js +229 -23
  62. package/dist/runtime/server/utils/custom-secondary-storage.d.ts +6 -0
  63. package/dist/runtime/server/utils/custom-secondary-storage.js +8 -0
  64. package/dist/runtime/server/utils/session.d.ts +6 -8
  65. package/dist/runtime/server/utils/session.js +216 -4
  66. package/dist/runtime/server/virtual-modules.d.ts +27 -0
  67. package/dist/runtime/types/augment.d.ts +18 -4
  68. package/dist/runtime/types.d.ts +12 -13
  69. package/dist/types.d.mts +1 -1
  70. package/package.json +51 -47
@@ -1,6 +1,13 @@
1
+ import { createAuthClient } from "better-auth/vue";
1
2
  export function defineServerAuth(config) {
2
- return config;
3
+ return typeof config === "function" ? config : () => config;
3
4
  }
4
5
  export function defineClientAuth(config) {
5
- return config;
6
+ return (baseURL) => {
7
+ const ctx = { siteUrl: baseURL };
8
+ const resolved = typeof config === "function" ? config(ctx) : config;
9
+ const { baseURL: configuredBaseURL, ...resolvedOptions } = resolved;
10
+ const clientOptions = { ...resolvedOptions, baseURL: configuredBaseURL ?? baseURL };
11
+ return createAuthClient(clientOptions);
12
+ };
6
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;
@@ -2,8 +2,9 @@ import { defineEventHandler, getQuery } from "h3";
2
2
  import { paginationQuerySchema, sanitizeSearchPattern } from "./_schema.js";
3
3
  export default defineEventHandler(async (event) => {
4
4
  try {
5
- const { db, schema } = await import("hub:db");
6
- if (!schema.account)
5
+ const { db } = await import("@nuxthub/db");
6
+ const { schema } = await import("#auth/schema");
7
+ if (!schema?.account)
7
8
  return { accounts: [], total: 0, error: "Account table not found" };
8
9
  const query = paginationQuerySchema.parse(getQuery(event));
9
10
  const { page, limit, search } = query;
@@ -2,11 +2,16 @@ declare const _default: import("h3").EventHandler<import("h3").EventHandlerReque
2
2
  config: {
3
3
  module: {
4
4
  redirects: {
5
- login?: string;
6
- guest?: string;
5
+ login: string;
6
+ guest: string;
7
+ authenticated: string | undefined;
8
+ logout: string | undefined;
7
9
  };
8
- secondaryStorage: boolean;
10
+ preserveRedirect: boolean;
11
+ redirectQueryKey: string;
12
+ hubSecondaryStorage: boolean | "custom";
9
13
  useDatabase: boolean;
14
+ databaseProvider: "none" | "nuxthub";
10
15
  };
11
16
  server: {
12
17
  baseURL: any;
@@ -14,6 +19,7 @@ declare const _default: import("h3").EventHandler<import("h3").EventHandlerReque
14
19
  socialProviders: string[];
15
20
  plugins: any;
16
21
  trustedOrigins: any;
22
+ configuredTrustedOrigins: any;
17
23
  session: {
18
24
  expiresIn: string;
19
25
  updateAge: string;
@@ -1,13 +1,16 @@
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 {
6
- const auth = await serverAuth(event);
6
+ const auth = serverAuth(event);
7
7
  const options = auth.options;
8
+ const authContext = await auth.$context;
8
9
  const runtimeConfig = useRuntimeConfig();
9
10
  const publicAuth = runtimeConfig.public?.auth;
10
11
  const privateAuth = runtimeConfig.auth;
12
+ const configuredTrustedOrigins = Array.isArray(options.trustedOrigins) ? options.trustedOrigins : [];
13
+ const effectiveTrustedOrigins = authContext?.trustedOrigins || configuredTrustedOrigins;
11
14
  const sessionConfig = options.session || {};
12
15
  const expiresInDays = sessionConfig.expiresIn ? Math.round(sessionConfig.expiresIn / 86400) : 7;
13
16
  const updateAgeDays = sessionConfig.updateAge ? Math.round(sessionConfig.updateAge / 86400) : 1;
@@ -15,9 +18,17 @@ export default defineEventHandler(async (event) => {
15
18
  config: {
16
19
  // Module config (nuxt.config.ts)
17
20
  module: {
18
- redirects: publicAuth?.redirects || { login: "/login", guest: "/" },
19
- secondaryStorage: privateAuth?.secondaryStorage ?? false,
20
- useDatabase: publicAuth?.useDatabase ?? false
21
+ redirects: {
22
+ login: publicAuth?.redirects?.login ?? "/login",
23
+ guest: publicAuth?.redirects?.guest ?? "/",
24
+ authenticated: publicAuth?.redirects?.authenticated,
25
+ logout: publicAuth?.redirects?.logout
26
+ },
27
+ preserveRedirect: publicAuth?.preserveRedirect ?? true,
28
+ redirectQueryKey: publicAuth?.redirectQueryKey ?? "redirect",
29
+ hubSecondaryStorage: privateAuth?.hubSecondaryStorage ?? false,
30
+ useDatabase: publicAuth?.useDatabase ?? false,
31
+ databaseProvider: publicAuth?.databaseProvider ?? "none"
21
32
  },
22
33
  // Server config (server/auth.config.ts)
23
34
  server: {
@@ -25,7 +36,8 @@ export default defineEventHandler(async (event) => {
25
36
  basePath: options.basePath || "/api/auth",
26
37
  socialProviders: Object.keys(options.socialProviders || {}),
27
38
  plugins: (options.plugins || []).map((p) => p.id || "unknown"),
28
- trustedOrigins: options.trustedOrigins || [],
39
+ trustedOrigins: effectiveTrustedOrigins,
40
+ configuredTrustedOrigins,
29
41
  session: {
30
42
  expiresIn: `${expiresInDays} days`,
31
43
  updateAge: `${updateAgeDays} days`,
@@ -6,8 +6,9 @@ const deleteSessionSchema = z.object({
6
6
  export default defineEventHandler(async (event) => {
7
7
  try {
8
8
  const body = deleteSessionSchema.parse(await readBody(event));
9
- const { db, schema } = await import("hub:db");
10
- if (!schema.session)
9
+ const { db } = await import("@nuxthub/db");
10
+ const { schema } = await import("#auth/schema");
11
+ if (!schema?.session)
11
12
  throw createError({ statusCode: 500, message: "Session table not found" });
12
13
  const { eq } = await import("drizzle-orm");
13
14
  await db.delete(schema.session).where(eq(schema.session.id, body.id));
@@ -1,3 +1,5 @@
1
+ import type { Session } from 'better-auth/types';
2
+ type SafeSession = Pick<Session, 'id' | 'userId' | 'createdAt' | 'updatedAt' | 'expiresAt' | 'ipAddress' | 'userAgent'>;
1
3
  declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
2
4
  sessions: never[];
3
5
  total: number;
@@ -5,10 +7,10 @@ declare const _default: import("h3").EventHandler<import("h3").EventHandlerReque
5
7
  page?: undefined;
6
8
  limit?: undefined;
7
9
  } | {
8
- sessions: any;
10
+ sessions: SafeSession[];
9
11
  total: any;
10
- page: number;
11
- limit: number;
12
+ page: any;
13
+ limit: any;
12
14
  error?: undefined;
13
15
  }>>;
14
16
  export default _default;
@@ -2,8 +2,9 @@ import { defineEventHandler, getQuery } from "h3";
2
2
  import { paginationQuerySchema, sanitizeSearchPattern } from "./_schema.js";
3
3
  export default defineEventHandler(async (event) => {
4
4
  try {
5
- const { db, schema } = await import("hub:db");
6
- if (!schema.session)
5
+ const { db } = await import("@nuxthub/db");
6
+ const { schema } = await import("#auth/schema");
7
+ if (!schema?.session)
7
8
  return { sessions: [], total: 0, error: "Session table not found" };
8
9
  const query = paginationQuerySchema.parse(getQuery(event));
9
10
  const { page, limit, search } = query;
@@ -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;
@@ -2,8 +2,9 @@ import { defineEventHandler, getQuery } from "h3";
2
2
  import { paginationQuerySchema, sanitizeSearchPattern } from "./_schema.js";
3
3
  export default defineEventHandler(async (event) => {
4
4
  try {
5
- const { db, schema } = await import("hub:db");
6
- if (!schema.user)
5
+ const { db } = await import("@nuxthub/db");
6
+ const { schema } = await import("#auth/schema");
7
+ if (!schema?.user)
7
8
  return { users: [], total: 0, error: "User table not found" };
8
9
  const query = paginationQuerySchema.parse(getQuery(event));
9
10
  const { page, limit, search } = query;
@@ -1,6 +1,6 @@
1
1
  import { defineEventHandler, toWebRequest } from "h3";
2
2
  import { serverAuth } from "../../utils/auth.js";
3
3
  export default defineEventHandler(async (event) => {
4
- const auth = await serverAuth(event);
4
+ const auth = serverAuth(event);
5
5
  return auth.handler(toWebRequest(event));
6
6
  });
@@ -1,6 +1,7 @@
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
+ import { getUserSession, requireUserSession } from "../utils/session.js";
4
5
  export default defineEventHandler(async (event) => {
5
6
  const path = getRequestURL(event).pathname;
6
7
  if (!path.startsWith("/api/"))
@@ -1,3 +1,11 @@
1
1
  {
2
- "extends": "../../../.nuxt/tsconfig.server.json"
2
+ "extends": "../../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "baseUrl": ".",
5
+ "paths": {
6
+ "#nuxt-better-auth": ["../types/augment"]
7
+ }
8
+ },
9
+ "include": ["./**/*.ts", "./**/*.d.ts"],
10
+ "exclude": ["node_modules"]
3
11
  }
@@ -1,11 +1,19 @@
1
- import type { Auth } from 'better-auth';
1
+ import type { BetterAuthOptions } from 'better-auth';
2
2
  import type { H3Event } from 'h3';
3
+ import { betterAuth } from 'better-auth';
3
4
  import createServerAuth from '#auth/server';
4
- type AuthInstance = Auth<ReturnType<typeof createServerAuth>>;
5
- declare module 'h3' {
6
- interface H3EventContext {
7
- _betterAuth?: AuthInstance;
8
- }
9
- }
10
- export declare function serverAuth(event: H3Event): Promise<AuthInstance>;
5
+ type AuthOptions = ReturnType<typeof createServerAuth>;
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>>;
17
+ /** Returns Better Auth instance. Caches per resolved host (or single instance when siteUrl is explicit). */
18
+ export declare function serverAuth(event?: H3Event): AuthInstance;
11
19
  export {};
@@ -1,32 +1,238 @@
1
+ import { betterAuth } from "better-auth";
2
+ import { getRequestHost, getRequestProtocol } from "h3";
3
+ import { useRuntimeConfig } from "nitropack/runtime";
4
+ import { withoutProtocol } from "ufo";
1
5
  import { createDatabase, db } from "#auth/database";
2
6
  import { createSecondaryStorage } from "#auth/secondary-storage";
3
7
  import createServerAuth from "#auth/server";
4
- import { betterAuth } from "better-auth";
5
- import { consola } from "consola";
6
- import { getRequestURL } from "h3";
7
- import { useRuntimeConfig } from "nitropack/runtime";
8
- const logger = consola.withTag("nuxt-better-auth");
9
- function getBaseURL(event, siteUrl) {
10
- if (siteUrl)
11
- return siteUrl;
12
- const origin = getRequestURL(event).origin;
13
- if (process.env.NODE_ENV === "production")
14
- throw new Error("siteUrl must be configured in production. Set NUXT_PUBLIC_SITE_URL or configure in nuxt.config.");
15
- logger.warn("siteUrl not set, auto-detected:", origin);
8
+ import { resolveCustomSecondaryStorageRequirement } from "./custom-secondary-storage.js";
9
+ const _authCache = /* @__PURE__ */ new Map();
10
+ const requestAuthKey = Symbol.for("nuxt-better-auth.requestAuth");
11
+ let _baseURLInferenceLogged = false;
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
+ }
25
+ function normalizeLoopbackOrigin(origin) {
26
+ if (!import.meta.dev)
27
+ return origin;
28
+ try {
29
+ const url = new URL(origin);
30
+ if (url.hostname === "127.0.0.1" || url.hostname === "::1" || url.hostname === "[::1]") {
31
+ url.hostname = "localhost";
32
+ return url.origin;
33
+ }
34
+ } catch {
35
+ }
16
36
  return origin;
17
37
  }
18
- export async function serverAuth(event) {
19
- if (event.context._betterAuth)
20
- return event.context._betterAuth;
38
+ function logInferredBaseURL(baseURL, source) {
39
+ if (!import.meta.dev || _baseURLInferenceLogged)
40
+ return;
41
+ _baseURLInferenceLogged = true;
42
+ console.warn(`[nuxt-better-auth] Using inferred baseURL "${baseURL}" from ${source}. Set runtimeConfig.public.siteUrl for deterministic OAuth callbacks.`);
43
+ }
44
+ function validateURL(url) {
45
+ try {
46
+ return normalizeLoopbackOrigin(new URL(url).origin);
47
+ } catch {
48
+ throw new Error(`Invalid siteUrl: "${url}". Must be a valid URL.`);
49
+ }
50
+ }
51
+ function resolveConfiguredSiteUrl(config) {
52
+ if (typeof config.public.siteUrl !== "string" || !config.public.siteUrl)
53
+ return void 0;
54
+ return validateURL(config.public.siteUrl);
55
+ }
56
+ function resolveEventOrigin(event) {
57
+ if (!event)
58
+ return void 0;
59
+ const host = getRequestHost(event, { xForwardedHost: true });
60
+ const protocol = getRequestProtocol(event, { xForwardedProto: true });
61
+ if (!host || !protocol)
62
+ return void 0;
63
+ try {
64
+ return validateURL(`${protocol}://${host}`);
65
+ } catch {
66
+ return void 0;
67
+ }
68
+ }
69
+ function getNitroOrigin() {
70
+ const cert = process.env.NITRO_SSL_CERT;
71
+ const key = process.env.NITRO_SSL_KEY;
72
+ let host = process.env.NITRO_HOST || process.env.HOST;
73
+ let port;
74
+ if (import.meta.dev)
75
+ port = process.env.NITRO_PORT || process.env.PORT || "3000";
76
+ let protocol = cert && key || !import.meta.dev ? "https" : "http";
77
+ try {
78
+ if ((import.meta.dev || import.meta.prerender) && process.env.__NUXT_DEV__) {
79
+ const origin = JSON.parse(process.env.__NUXT_DEV__).proxy.url;
80
+ host = withoutProtocol(origin);
81
+ protocol = origin.includes("https") ? "https" : "http";
82
+ } else if ((import.meta.dev || import.meta.prerender) && process.env.NUXT_VITE_NODE_OPTIONS) {
83
+ const origin = JSON.parse(process.env.NUXT_VITE_NODE_OPTIONS).baseURL.replace("/__nuxt_vite_node__", "");
84
+ host = withoutProtocol(origin);
85
+ protocol = origin.includes("https") ? "https" : "http";
86
+ }
87
+ } catch {
88
+ }
89
+ if (!host)
90
+ return void 0;
91
+ if (host.startsWith("[") && host.includes("]:")) {
92
+ const lastBracketColon = host.lastIndexOf("]:");
93
+ const extractedPort = host.slice(lastBracketColon + 2);
94
+ host = host.slice(0, lastBracketColon + 1);
95
+ if (extractedPort)
96
+ port = extractedPort;
97
+ } else if (host.includes(":") && !host.startsWith("[")) {
98
+ const hostParts = host.split(":");
99
+ port = hostParts.pop();
100
+ host = hostParts.join(":");
101
+ }
102
+ const portSuffix = port ? `:${port}` : "";
103
+ return `${protocol}://${host}${portSuffix}`;
104
+ }
105
+ function resolveEnvironmentOrigin() {
106
+ const nitroOrigin = getNitroOrigin();
107
+ if (nitroOrigin)
108
+ return { origin: validateURL(nitroOrigin), source: "Nitro environment detection" };
109
+ if (process.env.VERCEL_URL)
110
+ return { origin: validateURL(`https://${process.env.VERCEL_URL}`), source: "VERCEL_URL" };
111
+ if (process.env.CF_PAGES_URL)
112
+ return { origin: validateURL(`https://${process.env.CF_PAGES_URL}`), source: "CF_PAGES_URL" };
113
+ if (process.env.URL)
114
+ return { origin: validateURL(process.env.URL.startsWith("http") ? process.env.URL : `https://${process.env.URL}`), source: "URL" };
115
+ return void 0;
116
+ }
117
+ function resolveDevFallback() {
118
+ if (!import.meta.dev)
119
+ return void 0;
120
+ return { origin: "http://localhost:3000", source: "development fallback" };
121
+ }
122
+ function getBaseURL(event) {
123
+ const config = useRuntimeConfig();
124
+ const configuredSiteUrl = resolveConfiguredSiteUrl(config);
125
+ if (configuredSiteUrl)
126
+ return configuredSiteUrl;
127
+ const eventOrigin = resolveEventOrigin(event);
128
+ if (eventOrigin) {
129
+ logInferredBaseURL(eventOrigin, "request origin");
130
+ return eventOrigin;
131
+ }
132
+ const environmentOrigin = resolveEnvironmentOrigin();
133
+ if (environmentOrigin) {
134
+ logInferredBaseURL(environmentOrigin.origin, environmentOrigin.source);
135
+ return environmentOrigin.origin;
136
+ }
137
+ const devFallback = resolveDevFallback();
138
+ if (devFallback) {
139
+ logInferredBaseURL(devFallback.origin, devFallback.source);
140
+ return devFallback.origin;
141
+ }
142
+ throw new Error("siteUrl required. Set NUXT_PUBLIC_SITE_URL.");
143
+ }
144
+ function dedupeOrigins(origins) {
145
+ return [...new Set(origins)];
146
+ }
147
+ function getDevTrustedOrigins() {
148
+ const fallbackOrigin = "http://localhost:3000";
149
+ const nitroOrigin = getNitroOrigin();
150
+ if (!nitroOrigin)
151
+ return [fallbackOrigin];
152
+ try {
153
+ const url = new URL(nitroOrigin);
154
+ const protocol = url.protocol === "https:" ? "https" : "http";
155
+ const port = url.port || "3000";
156
+ const localhostOrigin = `${protocol}://localhost:${port}`;
157
+ return dedupeOrigins([localhostOrigin, url.origin]);
158
+ } catch {
159
+ return [fallbackOrigin];
160
+ }
161
+ }
162
+ function getRequestOrigin(request) {
163
+ if (!request)
164
+ return void 0;
165
+ try {
166
+ return new URL(request.url).origin;
167
+ } catch {
168
+ return void 0;
169
+ }
170
+ }
171
+ function withDevTrustedOrigins(trustedOrigins) {
172
+ if (!import.meta.dev)
173
+ return trustedOrigins;
174
+ const devOrigins = getDevTrustedOrigins();
175
+ const mergeOrigins = (origins, request) => {
176
+ const validOrigins = origins.filter((origin) => typeof origin === "string");
177
+ const requestOrigin = getRequestOrigin(request);
178
+ return dedupeOrigins(requestOrigin ? [...validOrigins, ...devOrigins, requestOrigin] : [...validOrigins, ...devOrigins]);
179
+ };
180
+ if (typeof trustedOrigins === "function") {
181
+ return async (request) => {
182
+ const resolvedOrigins = await trustedOrigins(request);
183
+ return mergeOrigins(resolvedOrigins, request);
184
+ };
185
+ }
186
+ if (Array.isArray(trustedOrigins)) {
187
+ const baseOrigins = mergeOrigins(trustedOrigins);
188
+ return async (request) => {
189
+ return mergeOrigins(baseOrigins, request);
190
+ };
191
+ }
192
+ return async (request) => {
193
+ return mergeOrigins([], request);
194
+ };
195
+ }
196
+ export function serverAuth(event) {
21
197
  const runtimeConfig = useRuntimeConfig();
22
- const database = createDatabase();
23
- const userConfig = createServerAuth({ runtimeConfig, db });
24
- event.context._betterAuth = betterAuth({
198
+ const siteUrl = getBaseURL(event);
199
+ const requestOrigin = resolveEventOrigin(event);
200
+ const hasExplicitSiteUrl = runtimeConfig.public.siteUrl && typeof runtimeConfig.public.siteUrl === "string";
201
+ const cacheKey = hasExplicitSiteUrl ? "__explicit__" : siteUrl;
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);
208
+ const hubSecondaryStorage = runtimeConfig.auth?.hubSecondaryStorage;
209
+ const customSecondaryStorage = resolveCustomSecondaryStorageRequirement(hubSecondaryStorage, userConfig.secondaryStorage != null, Boolean(import.meta.dev));
210
+ if (customSecondaryStorage?.shouldThrow)
211
+ throw new Error(customSecondaryStorage.message);
212
+ if (customSecondaryStorage?.shouldWarn && !_customSecondaryStorageMisconfigWarned) {
213
+ _customSecondaryStorageMisconfigWarned = true;
214
+ console.warn(customSecondaryStorage.message);
215
+ }
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 = {
25
225
  ...userConfig,
26
- ...database && { database },
27
- secondaryStorage: createSecondaryStorage(),
226
+ ...database ? { database } : {},
227
+ ...hubSecondaryStorage === true ? { secondaryStorage: createSecondaryStorage() } : {},
28
228
  secret: runtimeConfig.betterAuthSecret,
29
- baseURL: getBaseURL(event, runtimeConfig.public.siteUrl)
30
- });
31
- return event.context._betterAuth;
229
+ baseURL: siteUrl,
230
+ trustedOrigins
231
+ };
232
+ const auth = betterAuth(authOptions);
233
+ if (requestContext)
234
+ requestContext[requestAuthKey] = auth;
235
+ if (!database)
236
+ _authCache.set(cacheKey, auth);
237
+ return auth;
32
238
  }
@@ -0,0 +1,6 @@
1
+ export type HubSecondaryStorageMode = boolean | 'custom' | undefined;
2
+ export declare function resolveCustomSecondaryStorageRequirement(hubSecondaryStorage: HubSecondaryStorageMode, userHasSecondaryStorage: boolean, isDev: boolean): {
3
+ shouldThrow: boolean;
4
+ shouldWarn: boolean;
5
+ message: string;
6
+ } | null;
@@ -0,0 +1,8 @@
1
+ export function resolveCustomSecondaryStorageRequirement(hubSecondaryStorage, userHasSecondaryStorage, isDev) {
2
+ if (hubSecondaryStorage !== "custom")
3
+ return null;
4
+ if (userHasSecondaryStorage)
5
+ return null;
6
+ const message = '[nuxt-better-auth] hubSecondaryStorage: "custom" requires secondaryStorage in defineServerAuth().';
7
+ return { shouldThrow: !isDev, shouldWarn: isDev, message };
8
+ }
@@ -1,9 +1,7 @@
1
1
  import type { H3Event } from 'h3';
2
- import type { AuthSession, AuthUser, RequireSessionOptions } from '../../types.js';
3
- interface FullSession {
4
- user: AuthUser;
5
- session: AuthSession;
6
- }
7
- export declare function getUserSession(event: H3Event): Promise<FullSession | null>;
8
- export declare function requireUserSession(event: H3Event, options?: RequireSessionOptions): Promise<FullSession>;
9
- export {};
2
+ import type { AppSession, AuthSession, RequireSessionOptions } from '#nuxt-better-auth';
3
+ export declare function getRequestSession(event: H3Event): Promise<AppSession | null>;
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>;
7
+ export declare function requireUserSession(event: H3Event, options?: RequireSessionOptions): Promise<AppSession>;