@nuxtjs/better-auth 0.0.0 → 0.1.3

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 (95) hide show
  1. package/README.md +67 -0
  2. package/dist/module.d.mts +47 -0
  3. package/dist/module.json +12 -0
  4. package/dist/module.mjs +1468 -0
  5. package/dist/runtime/app/components/BetterAuthState.d.vue.ts +20 -0
  6. package/dist/runtime/app/components/BetterAuthState.vue +9 -0
  7. package/dist/runtime/app/components/BetterAuthState.vue.d.ts +20 -0
  8. package/dist/runtime/app/composables/runWithSessionRefresh.d.ts +1 -0
  9. package/dist/runtime/app/composables/runWithSessionRefresh.js +12 -0
  10. package/dist/runtime/app/composables/useAction.d.ts +2 -0
  11. package/dist/runtime/app/composables/useAction.js +6 -0
  12. package/dist/runtime/app/composables/useAuthAsyncData.d.ts +6 -0
  13. package/dist/runtime/app/composables/useAuthAsyncData.js +16 -0
  14. package/dist/runtime/app/composables/useAuthClient.d.ts +9 -0
  15. package/dist/runtime/app/composables/useAuthClient.js +35 -0
  16. package/dist/runtime/app/composables/useAuthClientAction.d.ts +3 -0
  17. package/dist/runtime/app/composables/useAuthClientAction.js +15 -0
  18. package/dist/runtime/app/composables/useAuthRequestFetch.d.ts +11 -0
  19. package/dist/runtime/app/composables/useAuthRequestFetch.js +4 -0
  20. package/dist/runtime/app/composables/useSignIn.d.ts +16 -0
  21. package/dist/runtime/app/composables/useSignIn.js +8 -0
  22. package/dist/runtime/app/composables/useSignUp.d.ts +5 -0
  23. package/dist/runtime/app/composables/useSignUp.js +8 -0
  24. package/dist/runtime/app/composables/useUserSession.d.ts +23 -0
  25. package/dist/runtime/app/composables/useUserSession.js +247 -0
  26. package/dist/runtime/app/composables/useUserSessionState.d.ts +3 -0
  27. package/dist/runtime/app/composables/useUserSessionState.js +4 -0
  28. package/dist/runtime/app/internal/auth-action-error.d.ts +3 -0
  29. package/dist/runtime/app/internal/auth-action-error.js +33 -0
  30. package/dist/runtime/app/internal/auth-action-handles.d.ts +21 -0
  31. package/dist/runtime/app/internal/auth-action-handles.js +105 -0
  32. package/dist/runtime/app/internal/redirect-helpers.d.ts +4 -0
  33. package/dist/runtime/app/internal/redirect-helpers.js +37 -0
  34. package/dist/runtime/app/internal/session-fetch.d.ts +12 -0
  35. package/dist/runtime/app/internal/session-fetch.js +56 -0
  36. package/dist/runtime/app/internal/utils.d.ts +1 -0
  37. package/dist/runtime/app/internal/utils.js +3 -0
  38. package/dist/runtime/app/internal/vue-safe-auth-proxy.d.ts +3 -0
  39. package/dist/runtime/app/internal/vue-safe-auth-proxy.js +68 -0
  40. package/dist/runtime/app/internal/wrap-auth-method.d.ts +18 -0
  41. package/dist/runtime/app/internal/wrap-auth-method.js +69 -0
  42. package/dist/runtime/app/middleware/auth.global.d.ts +13 -0
  43. package/dist/runtime/app/middleware/auth.global.js +104 -0
  44. package/dist/runtime/app/pages/__better-auth-devtools.d.vue.ts +3 -0
  45. package/dist/runtime/app/pages/__better-auth-devtools.vue +380 -0
  46. package/dist/runtime/app/pages/__better-auth-devtools.vue.d.ts +3 -0
  47. package/dist/runtime/app/plugins/session.client.d.ts +2 -0
  48. package/dist/runtime/app/plugins/session.client.js +16 -0
  49. package/dist/runtime/app/plugins/session.server.d.ts +2 -0
  50. package/dist/runtime/app/plugins/session.server.js +24 -0
  51. package/dist/runtime/composables.d.ts +12 -0
  52. package/dist/runtime/composables.js +10 -0
  53. package/dist/runtime/config.d.ts +100 -0
  54. package/dist/runtime/config.js +13 -0
  55. package/dist/runtime/internal/auth-route-rules.d.ts +1 -0
  56. package/dist/runtime/internal/auth-route-rules.js +24 -0
  57. package/dist/runtime/server/api/_better-auth/_schema.d.ts +4 -0
  58. package/dist/runtime/server/api/_better-auth/_schema.js +12 -0
  59. package/dist/runtime/server/api/_better-auth/accounts.get.d.ts +2 -0
  60. package/dist/runtime/server/api/_better-auth/accounts.get.js +29 -0
  61. package/dist/runtime/server/api/_better-auth/config.get.d.ts +2 -0
  62. package/dist/runtime/server/api/_better-auth/config.get.js +58 -0
  63. package/dist/runtime/server/api/_better-auth/sessions.delete.d.ts +2 -0
  64. package/dist/runtime/server/api/_better-auth/sessions.delete.js +23 -0
  65. package/dist/runtime/server/api/_better-auth/sessions.get.d.ts +2 -0
  66. package/dist/runtime/server/api/_better-auth/sessions.get.js +44 -0
  67. package/dist/runtime/server/api/_better-auth/users.get.d.ts +2 -0
  68. package/dist/runtime/server/api/_better-auth/users.get.js +35 -0
  69. package/dist/runtime/server/api/auth/[...all].d.ts +2 -0
  70. package/dist/runtime/server/api/auth/[...all].js +6 -0
  71. package/dist/runtime/server/internal/nitro-compat.d.ts +1 -0
  72. package/dist/runtime/server/internal/nitro-compat.js +1 -0
  73. package/dist/runtime/server/internal/nitro2.d.ts +8 -0
  74. package/dist/runtime/server/internal/nitro2.js +29 -0
  75. package/dist/runtime/server/internal/nitro3.d.ts +10 -0
  76. package/dist/runtime/server/internal/nitro3.js +60 -0
  77. package/dist/runtime/server/middleware/route-access.d.ts +2 -0
  78. package/dist/runtime/server/middleware/route-access.js +29 -0
  79. package/dist/runtime/server/tsconfig.json +12 -0
  80. package/dist/runtime/server/utils/auth.d.ts +20 -0
  81. package/dist/runtime/server/utils/auth.js +246 -0
  82. package/dist/runtime/server/utils/custom-secondary-storage.d.ts +6 -0
  83. package/dist/runtime/server/utils/custom-secondary-storage.js +8 -0
  84. package/dist/runtime/server/utils/session.d.ts +8 -0
  85. package/dist/runtime/server/utils/session.js +280 -0
  86. package/dist/runtime/server/virtual-modules.d.ts +27 -0
  87. package/dist/runtime/types/augment.d.ts +56 -0
  88. package/dist/runtime/types/augment.js +0 -0
  89. package/dist/runtime/types.d.ts +21 -0
  90. package/dist/runtime/types.js +0 -0
  91. package/dist/runtime/utils/match-user.d.ts +2 -0
  92. package/dist/runtime/utils/match-user.js +13 -0
  93. package/dist/types.d.mts +11 -0
  94. package/package.json +111 -10
  95. package/index.js +0 -1
@@ -0,0 +1,1468 @@
1
+ import { existsSync, statSync, writeFileSync, readFileSync } from 'node:fs';
2
+ import { mkdir, writeFile } from 'node:fs/promises';
3
+ import { getLayerDirectories, updateTemplates, addServerImportsDir, addServerImports, addServerScanDir, addServerHandler, addImportsDir, addPlugin, addComponentsDir, extendPages, addTemplate, hasNuxtModule, addTypeTemplate, defineNuxtModule, createResolver } from '@nuxt/kit';
4
+ import { consola as consola$1 } from 'consola';
5
+ import { isAbsolute, join, relative, dirname } from 'pathe';
6
+ import { defu } from 'defu';
7
+ import { toRouteMatcher, createRouter } from 'radix3';
8
+ import { generateDrizzleSchema as generateDrizzleSchema$1 } from 'auth/api';
9
+ import { randomBytes } from 'node:crypto';
10
+ import { isCI, isTest } from 'std-env';
11
+ export { defineClientAuth, defineServerAuth } from '../dist/runtime/config.js';
12
+
13
+ const version = "0.1.3";
14
+
15
+ const CONFIG_EXTENSIONS = [".ts", ".js"];
16
+ const CONFIG_EXTENSION_RE = /\.(?:ts|js)$/;
17
+ const DEFAULT_CONFIG_FILES = {
18
+ server: "server/auth.config",
19
+ client: "app/auth.config"
20
+ };
21
+ const OPTION_KEY_BY_KIND = {
22
+ server: "serverConfig",
23
+ client: "clientConfig"
24
+ };
25
+ function stripConfigExtension(path) {
26
+ return path.replace(CONFIG_EXTENSION_RE, "");
27
+ }
28
+ function defaultConfigExists(path) {
29
+ return CONFIG_EXTENSIONS.some((ext) => existsSync(`${path}${ext}`));
30
+ }
31
+ function getLayerDirectoriesWithConfigs(nuxt) {
32
+ const directories = getLayerDirectories(nuxt);
33
+ const layers = nuxt.options._layers;
34
+ return directories.map((directory, index) => ({ directory, layer: layers[index] }));
35
+ }
36
+ function getProjectDirectory(nuxt) {
37
+ return getLayerDirectories(nuxt)[0];
38
+ }
39
+ function getDefaultConfigPath(nuxt, kind) {
40
+ const project = getProjectDirectory(nuxt);
41
+ return kind === "server" ? join(project.server, "auth.config") : join(project.app, "auth.config");
42
+ }
43
+ function getLayerDefaultConfigPath(nuxt, kind, configExists) {
44
+ for (const { directory } of getLayerDirectoriesWithConfigs(nuxt)) {
45
+ const candidate = kind === "server" ? join(directory.server, "auth.config") : join(directory.app, "auth.config");
46
+ if (configExists(candidate)) {
47
+ return {
48
+ path: candidate,
49
+ declaringLayerRoot: directory.root
50
+ };
51
+ }
52
+ }
53
+ }
54
+ function resolveDeclaringLayerRoot(nuxt, kind, file) {
55
+ const optionKey = OPTION_KEY_BY_KIND[kind];
56
+ for (const { directory, layer } of getLayerDirectoriesWithConfigs(nuxt)) {
57
+ const declared = layer?.config?.auth?.[optionKey];
58
+ if (typeof declared === "string" && stripConfigExtension(declared) === file)
59
+ return directory.root;
60
+ }
61
+ return getProjectDirectory(nuxt).root;
62
+ }
63
+ function getRelativeConfigFile(nuxt, path) {
64
+ return relative(getProjectDirectory(nuxt).root, path);
65
+ }
66
+ function getEffectiveModuleConfigFile(nuxt, kind) {
67
+ const optionKey = OPTION_KEY_BY_KIND[kind];
68
+ const authOptions = nuxt.options.auth;
69
+ return authOptions?.[optionKey] ?? DEFAULT_CONFIG_FILES[kind];
70
+ }
71
+ function resolveAuthConfigDescriptor(nuxt, kind, file = getEffectiveModuleConfigFile(nuxt, kind), dependencies = {}) {
72
+ const configExists = dependencies.configExists ?? defaultConfigExists;
73
+ const configuredFile = stripConfigExtension(file);
74
+ if (isAbsolute(configuredFile)) {
75
+ const declaringLayerRoot2 = resolveDeclaringLayerRoot(nuxt, kind, configuredFile);
76
+ const exists2 = configExists(configuredFile);
77
+ return {
78
+ kind,
79
+ configuredFile,
80
+ file: configuredFile,
81
+ path: configuredFile,
82
+ declaringLayerRoot: declaringLayerRoot2,
83
+ isDefault: false,
84
+ isExplicit: true,
85
+ exists: exists2,
86
+ shouldCreateDefaultFile: false
87
+ };
88
+ }
89
+ if (configuredFile === DEFAULT_CONFIG_FILES[kind]) {
90
+ const project = getProjectDirectory(nuxt);
91
+ const discovered = getLayerDefaultConfigPath(nuxt, kind, configExists);
92
+ const path2 = discovered?.path ?? getDefaultConfigPath(nuxt, kind);
93
+ const declaringLayerRoot2 = discovered?.declaringLayerRoot ?? project.root;
94
+ const exists2 = configExists(path2);
95
+ return {
96
+ kind,
97
+ configuredFile,
98
+ file: getRelativeConfigFile(nuxt, path2),
99
+ path: path2,
100
+ declaringLayerRoot: declaringLayerRoot2,
101
+ isDefault: true,
102
+ isExplicit: false,
103
+ exists: exists2,
104
+ shouldCreateDefaultFile: !exists2
105
+ };
106
+ }
107
+ const declaringLayerRoot = resolveDeclaringLayerRoot(nuxt, kind, configuredFile);
108
+ const path = join(declaringLayerRoot, configuredFile);
109
+ const exists = configExists(path);
110
+ return {
111
+ kind,
112
+ configuredFile,
113
+ file: getRelativeConfigFile(nuxt, path),
114
+ path,
115
+ declaringLayerRoot,
116
+ isDefault: false,
117
+ isExplicit: true,
118
+ exists,
119
+ shouldCreateDefaultFile: false
120
+ };
121
+ }
122
+ function resolveAuthConfigDescriptors(nuxt, files = {}, dependencies = {}) {
123
+ return {
124
+ server: resolveAuthConfigDescriptor(nuxt, "server", files.server, dependencies),
125
+ client: resolveAuthConfigDescriptor(nuxt, "client", files.client, dependencies)
126
+ };
127
+ }
128
+
129
+ function resolveNitroCompatibilityImports(nuxtVersion) {
130
+ const major = Number.parseInt(nuxtVersion, 10);
131
+ const nitroV3 = Number.isFinite(major) && major >= 5;
132
+ return {
133
+ h3: nitroV3 ? "nitro/h3" : "h3",
134
+ runtime: nitroV3 ? "nitro3" : "nitro2",
135
+ types: nitroV3 ? "nitro/types" : "nitropack/types"
136
+ };
137
+ }
138
+
139
+ function setupDevTools(nuxt) {
140
+ const hookable = nuxt;
141
+ hookable.hook("devtools:customTabs", (tabs) => {
142
+ tabs.push({
143
+ category: "server",
144
+ name: "better-auth",
145
+ title: "Auth",
146
+ icon: "simple-icons:betterauth",
147
+ view: {
148
+ type: "iframe",
149
+ src: "/__better-auth-devtools"
150
+ }
151
+ });
152
+ });
153
+ }
154
+
155
+ function registerTemplateHmrHook(nuxt) {
156
+ nuxt.hook("builder:watch", async (_event, relativePath) => {
157
+ if (relativePath.includes("auth.config"))
158
+ await updateTemplates({ filter: (t) => t.filename.includes("nuxt-better-auth") });
159
+ });
160
+ }
161
+ function registerServerRuntime(input) {
162
+ const { clientOnly, resolve } = input;
163
+ if (!clientOnly) {
164
+ addServerImportsDir(resolve("./runtime/server/utils"));
165
+ addServerImports([{ name: "defineServerAuth", from: resolve("./runtime/config") }]);
166
+ addServerScanDir(resolve("./runtime/server/middleware"));
167
+ addServerHandler({ route: "/api/auth/**", handler: resolve("./runtime/server/api/auth/[...all]") });
168
+ }
169
+ addImportsDir(resolve("./runtime/app/composables"));
170
+ addImportsDir(resolve("./runtime/utils"));
171
+ if (!clientOnly)
172
+ addPlugin({ src: resolve("./runtime/app/plugins/session.server"), mode: "server" });
173
+ addPlugin({ src: resolve("./runtime/app/plugins/session.client"), mode: "client" });
174
+ addComponentsDir({ path: resolve("./runtime/app/components") });
175
+ }
176
+ function registerAuthMiddlewareHook(nuxt, resolve) {
177
+ nuxt.hook("app:resolve", (app) => {
178
+ app.middleware.push({ name: "auth", path: resolve("./runtime/app/middleware/auth.global"), global: true });
179
+ });
180
+ }
181
+ function registerPrepareTypesHook(input) {
182
+ const { nuxt, serverDir, hasHubDb } = input;
183
+ nuxt.hook("prepare:types", ({ nodeTsConfig, nodeReferences, sharedReferences }) => {
184
+ nodeTsConfig.compilerOptions ||= {};
185
+ nodeTsConfig.compilerOptions.paths ||= {};
186
+ const projectReferenceTypePaths = [
187
+ join(nuxt.options.buildDir, "types/nitro-imports.d.ts"),
188
+ join(nuxt.options.buildDir, "types/auth-database.d.ts"),
189
+ join(nuxt.options.buildDir, "types/auth-schema.d.ts"),
190
+ join(nuxt.options.buildDir, "types/auth-secondary-storage.d.ts")
191
+ ];
192
+ if (hasHubDb)
193
+ projectReferenceTypePaths.push(join(nuxt.options.buildDir, "hub/db.d.ts"));
194
+ const exactNodeAliases = {
195
+ "#server": serverDir,
196
+ "#auth/server": nuxt.options.alias["#auth/server"],
197
+ "#auth/client": nuxt.options.alias["#auth/client"],
198
+ "#auth/database": nuxt.options.alias["#auth/database"],
199
+ "#auth/schema": nuxt.options.alias["#auth/schema"],
200
+ "#auth/secondary-storage": nuxt.options.alias["#auth/secondary-storage"],
201
+ "#auth/route-rules": nuxt.options.alias["#auth/route-rules"]
202
+ };
203
+ for (const [key, value] of Object.entries(exactNodeAliases)) {
204
+ if (typeof value === "string")
205
+ nodeTsConfig.compilerOptions.paths[key] = [value];
206
+ }
207
+ for (const [key, value] of Object.entries(nuxt.options.alias)) {
208
+ if (typeof value !== "string" || !isAbsolute(value))
209
+ continue;
210
+ nodeTsConfig.compilerOptions.paths[key] ||= [value];
211
+ if (!key.includes("*") && existsSync(value) && statSync(value).isDirectory())
212
+ nodeTsConfig.compilerOptions.paths[`${key}/*`] ||= [join(value, "*")];
213
+ }
214
+ nodeTsConfig.compilerOptions.paths["#server/*"] = [join(serverDir, "*")];
215
+ for (const path of projectReferenceTypePaths) {
216
+ if (!nodeReferences.some((reference) => "path" in reference && reference.path === path))
217
+ nodeReferences.push({ path });
218
+ if (!sharedReferences.some((reference) => "path" in reference && reference.path === path))
219
+ sharedReferences.push({ path });
220
+ }
221
+ });
222
+ }
223
+ function registerNuxtHubDatabaseExternalHook(nuxt) {
224
+ nuxt.hook("nitro:config", (nitroConfig) => {
225
+ nitroConfig.externals ||= {};
226
+ nitroConfig.externals.external ||= [];
227
+ if (!nitroConfig.externals.external.includes("@nuxthub/db"))
228
+ nitroConfig.externals.external.push("@nuxthub/db");
229
+ });
230
+ }
231
+ async function registerDevtools(input) {
232
+ const { nuxt, clientOnly, hasHubDb, resolve } = input;
233
+ const isProduction = process.env.NODE_ENV === "production" || !nuxt.options.dev;
234
+ if (isProduction || clientOnly)
235
+ return;
236
+ setupDevTools(nuxt);
237
+ addServerHandler({ route: "/api/_better-auth/config", method: "get", handler: resolve("./runtime/server/api/_better-auth/config.get") });
238
+ if (hasHubDb) {
239
+ const handlers = [
240
+ { route: "/api/_better-auth/sessions", method: "get", handler: resolve("./runtime/server/api/_better-auth/sessions.get") },
241
+ { route: "/api/_better-auth/sessions", method: "delete", handler: resolve("./runtime/server/api/_better-auth/sessions.delete") },
242
+ { route: "/api/_better-auth/users", method: "get", handler: resolve("./runtime/server/api/_better-auth/users.get") },
243
+ { route: "/api/_better-auth/accounts", method: "get", handler: resolve("./runtime/server/api/_better-auth/accounts.get") }
244
+ ];
245
+ handlers.forEach((handler) => addServerHandler(handler));
246
+ }
247
+ extendPages((pages) => {
248
+ pages.push({ name: "better-auth-devtools", path: "/__better-auth-devtools", file: resolve("./runtime/app/pages/__better-auth-devtools.vue"), meta: { layout: false } });
249
+ });
250
+ }
251
+ function registerRouteRulesMetaHook(nuxt) {
252
+ nuxt.hook("pages:extend", (pages) => {
253
+ const options = nuxt.options;
254
+ const routeRules = options.nitro?.routeRules || options.routeRules || {};
255
+ if (!Object.keys(routeRules).length)
256
+ return;
257
+ const matcher = toRouteMatcher(createRouter({ routes: routeRules }));
258
+ const applyMetaFromRules = (page) => {
259
+ const matches = matcher.matchAll(page.path);
260
+ if (!matches.length)
261
+ return;
262
+ const matchedRules = defu({}, ...matches.reverse());
263
+ if (matchedRules.auth !== void 0) {
264
+ page.meta = page.meta || {};
265
+ page.meta.auth = matchedRules.auth;
266
+ }
267
+ page.children?.forEach((child) => applyMetaFromRules(child));
268
+ };
269
+ pages.forEach((page) => applyMetaFromRules(page));
270
+ });
271
+ }
272
+
273
+ function dialectToProvider(dialect) {
274
+ return dialect === "postgresql" ? "pg" : dialect;
275
+ }
276
+ async function generateDrizzleSchema(authOptions, dialect, schemaOptions) {
277
+ const provider = dialectToProvider(dialect);
278
+ const options = {
279
+ ...authOptions,
280
+ advanced: {
281
+ ...authOptions.advanced,
282
+ database: {
283
+ ...authOptions.advanced?.database,
284
+ ...schemaOptions?.useUuid && { generateId: "uuid" }
285
+ }
286
+ }
287
+ };
288
+ const adapter = {
289
+ id: "drizzle",
290
+ options: {
291
+ provider,
292
+ camelCase: schemaOptions?.casing !== "snake_case",
293
+ schemaName: schemaOptions?.schemaName,
294
+ adapterConfig: { usePlural: schemaOptions?.usePlural ?? false }
295
+ }
296
+ };
297
+ const result = await generateDrizzleSchema$1({
298
+ adapter,
299
+ options
300
+ });
301
+ if (!result.code) {
302
+ throw new Error(`Schema generation returned empty result for ${dialect}`);
303
+ }
304
+ return result.code;
305
+ }
306
+ function loadLocalEnv(rootDir) {
307
+ if (!rootDir)
308
+ return;
309
+ const envPath = join(rootDir, ".env.local");
310
+ if (!existsSync(envPath))
311
+ return;
312
+ process.loadEnvFile(envPath);
313
+ }
314
+ async function loadUserAuthConfig(configPath, throwOnError = false, alias, runtimeConfig = {}, rootDir) {
315
+ const { createJiti } = await import('jiti');
316
+ const { defineServerAuth: runtimeDefineServerAuth } = await import('../dist/runtime/config.js');
317
+ const jiti = createJiti(import.meta.url, { interopDefault: true, moduleCache: false, alias });
318
+ const schemaGlobals = globalThis;
319
+ if (!schemaGlobals.__nuxtBetterAuthDefineServerAuth) {
320
+ runtimeDefineServerAuth._count = 0;
321
+ schemaGlobals.__nuxtBetterAuthDefineServerAuth = runtimeDefineServerAuth;
322
+ }
323
+ if (!schemaGlobals.defineServerAuth) {
324
+ schemaGlobals.defineServerAuth = schemaGlobals.__nuxtBetterAuthDefineServerAuth;
325
+ }
326
+ schemaGlobals.__nuxtBetterAuthDefineServerAuth._count++;
327
+ try {
328
+ loadLocalEnv(rootDir);
329
+ const mod = await jiti.import(configPath);
330
+ const configFn = mod.default;
331
+ if (typeof configFn === "function") {
332
+ return configFn({ runtimeConfig, db: null });
333
+ }
334
+ consola$1.warn("[@nuxtjs/better-auth] auth.config.ts does not export default. Expected: export default defineServerAuth(...)");
335
+ if (throwOnError) {
336
+ throw new Error("auth.config.ts must export default defineServerAuth(...)");
337
+ }
338
+ return {};
339
+ } catch (error) {
340
+ if (throwOnError) {
341
+ throw new Error(`Failed to load auth config: ${error instanceof Error ? error.message : error}`);
342
+ }
343
+ consola$1.error("[@nuxtjs/better-auth] Failed to load auth config for schema generation. Schema may be incomplete:", error);
344
+ return {};
345
+ } finally {
346
+ const sharedDefineServerAuth = schemaGlobals.__nuxtBetterAuthDefineServerAuth;
347
+ if (sharedDefineServerAuth) {
348
+ sharedDefineServerAuth._count--;
349
+ if (!sharedDefineServerAuth._count) {
350
+ schemaGlobals.__nuxtBetterAuthDefineServerAuth = void 0;
351
+ if (schemaGlobals.defineServerAuth === sharedDefineServerAuth) {
352
+ schemaGlobals.defineServerAuth = void 0;
353
+ }
354
+ }
355
+ }
356
+ }
357
+ }
358
+
359
+ function getHubDialect(hub) {
360
+ if (!hub?.db)
361
+ return void 0;
362
+ if (typeof hub.db === "string")
363
+ return hub.db;
364
+ if (typeof hub.db === "object" && hub.db !== null)
365
+ return hub.db.dialect;
366
+ return void 0;
367
+ }
368
+ function getHubCasing(hub) {
369
+ if (!hub?.db || typeof hub.db !== "object" || hub.db === null)
370
+ return void 0;
371
+ return hub.db.casing;
372
+ }
373
+
374
+ const NODE_MODULES_SEGMENT_RE = /[\\/]/;
375
+ function resolveSchemaSecondaryStorageInjection(hubSecondaryStorage, userHasSecondaryStorage, isProduction) {
376
+ if (hubSecondaryStorage === true)
377
+ return { inject: false };
378
+ if (hubSecondaryStorage !== "custom")
379
+ return { inject: false };
380
+ if (userHasSecondaryStorage)
381
+ return { inject: true };
382
+ const message = '[nuxt-better-auth] hubSecondaryStorage: "custom" requires secondaryStorage in defineServerAuth() to omit the session table from the generated schema.';
383
+ if (isProduction)
384
+ return { inject: false, error: message };
385
+ return { inject: false, warn: message };
386
+ }
387
+ function isInsideNodeModules(path) {
388
+ return path.split(NODE_MODULES_SEGMENT_RE).includes("node_modules");
389
+ }
390
+ function resolveHubSchemaPath(buildDir, rootDir, dialect, exists = existsSync) {
391
+ const rootTsPath = join(rootDir, ".nuxt", "better-auth", `schema.${dialect}.ts`);
392
+ if (isInsideNodeModules(buildDir) && exists(rootTsPath))
393
+ return rootTsPath;
394
+ const tsPath = join(buildDir, "better-auth", `schema.${dialect}.ts`);
395
+ if (exists(tsPath))
396
+ return tsPath;
397
+ const mjsPath = join(buildDir, "better-auth", `schema.${dialect}.mjs`);
398
+ if (exists(mjsPath))
399
+ return mjsPath;
400
+ return null;
401
+ }
402
+ async function loadAuthOptions(context) {
403
+ const isProduction = !context.nuxt.options.dev;
404
+ const configFile = `${context.serverConfigPath}.ts`;
405
+ const alias = Object.fromEntries(
406
+ Object.entries(context.nuxt.options.alias).filter(([, value]) => typeof value === "string").map(([key, value]) => [key, value])
407
+ );
408
+ const userConfig = await loadUserAuthConfig(configFile, isProduction, alias, context.nuxt.options.runtimeConfig, context.nuxt.options.rootDir);
409
+ const extendedConfig = {};
410
+ await context.nuxt.callHook("better-auth:config:extend", extendedConfig);
411
+ const plugins = [...userConfig.plugins || [], ...extendedConfig.plugins || []];
412
+ return { userConfig, plugins };
413
+ }
414
+ async function setupBetterAuthSchema(nuxt, serverConfigPath, options, consola, hubSecondaryStorage) {
415
+ const hub = nuxt.options.hub;
416
+ const dialect = getHubDialect(hub);
417
+ if (!dialect || !["sqlite", "postgresql", "mysql"].includes(dialect)) {
418
+ consola.warn(`Unsupported database dialect: ${dialect}`);
419
+ return;
420
+ }
421
+ const context = { nuxt, serverConfigPath };
422
+ try {
423
+ const { userConfig, plugins } = await loadAuthOptions(context);
424
+ const userHasSecondaryStorage = userConfig.secondaryStorage != null;
425
+ const secondaryStorageResolution = resolveSchemaSecondaryStorageInjection(hubSecondaryStorage, userHasSecondaryStorage, !nuxt.options.dev);
426
+ if (secondaryStorageResolution.error)
427
+ throw new Error(secondaryStorageResolution.error);
428
+ if (secondaryStorageResolution.warn)
429
+ consola.warn(secondaryStorageResolution.warn);
430
+ const authOptions = {
431
+ ...userConfig,
432
+ plugins,
433
+ secondaryStorage: secondaryStorageResolution.inject ? {
434
+ delete: async (_key) => {
435
+ },
436
+ get: async (_key) => null,
437
+ getAndDelete: async (_key) => null,
438
+ increment: async (_key, _ttl) => 1,
439
+ set: async (_key, _value, _ttl) => {
440
+ }
441
+ } : void 0
442
+ };
443
+ const hubCasing = getHubCasing(hub);
444
+ const schemaOptions = { ...options.schema, useUuid: userConfig.advanced?.database?.generateId === "uuid", casing: options.schema?.casing ?? hubCasing };
445
+ const schemaCode = await generateDrizzleSchema(authOptions, dialect, schemaOptions);
446
+ const schemaDir = join(nuxt.options.buildDir, "better-auth");
447
+ const schemaPathTs = join(schemaDir, `schema.${dialect}.ts`);
448
+ const schemaPathMjs = join(schemaDir, `schema.${dialect}.mjs`);
449
+ await mkdir(schemaDir, { recursive: true });
450
+ await writeFile(schemaPathTs, schemaCode);
451
+ await writeFile(schemaPathMjs, schemaCode);
452
+ if (isInsideNodeModules(nuxt.options.buildDir)) {
453
+ const rootSchemaDir = join(nuxt.options.rootDir, ".nuxt", "better-auth");
454
+ const rootSchemaPathTs = join(rootSchemaDir, `schema.${dialect}.ts`);
455
+ await mkdir(rootSchemaDir, { recursive: true });
456
+ await writeFile(rootSchemaPathTs, schemaCode);
457
+ }
458
+ addTemplate({ filename: `better-auth/schema.${dialect}.ts`, getContents: () => schemaCode, write: true });
459
+ addTemplate({ filename: `better-auth/schema.${dialect}.mjs`, getContents: () => schemaCode, write: true });
460
+ consola.info(`Generated ${dialect} schema (.ts + .mjs)`);
461
+ const nuxtWithHubHooks = nuxt;
462
+ nuxtWithHubHooks.hook("hub:db:schema:extend", ({ paths, dialect: hookDialect }) => {
463
+ const schemaPath = resolveHubSchemaPath(nuxt.options.buildDir, nuxt.options.rootDir, hookDialect);
464
+ if (schemaPath)
465
+ paths.unshift(schemaPath);
466
+ });
467
+ } catch (error) {
468
+ const isProduction = !nuxt.options.dev;
469
+ if (isProduction)
470
+ throw error;
471
+ consola.error("Failed to generate schema:", error);
472
+ throw error;
473
+ }
474
+ }
475
+
476
+ const DEFAULT_SECRET_ENV = "NUXT_BETTER_AUTH_SECRET";
477
+ const FALLBACK_SECRET_ENV = "BETTER_AUTH_SECRET";
478
+ const VERSIONED_SECRET_ENV = "BETTER_AUTH_SECRETS";
479
+ const generateSecret = () => randomBytes(32).toString("hex");
480
+ function readEnvFile(rootDir) {
481
+ const envPath = join(rootDir, ".env");
482
+ return existsSync(envPath) ? readFileSync(envPath, "utf-8") : "";
483
+ }
484
+ function hasEnvSecret(rootDir) {
485
+ const envFile = readEnvFile(rootDir);
486
+ return [DEFAULT_SECRET_ENV, FALLBACK_SECRET_ENV, VERSIONED_SECRET_ENV].some((name) => {
487
+ const match = envFile.match(new RegExp(`^${name}=(.+)$`, "m"));
488
+ return !!match && !!match[1] && match[1].trim().length > 0;
489
+ });
490
+ }
491
+ function appendSecretToEnv(rootDir, secret) {
492
+ const envPath = join(rootDir, ".env");
493
+ let content = readEnvFile(rootDir);
494
+ if (content.length > 0 && !content.endsWith("\n"))
495
+ content += "\n";
496
+ content += `${DEFAULT_SECRET_ENV}=${secret}
497
+ `;
498
+ writeFileSync(envPath, content, "utf-8");
499
+ }
500
+ async function promptForSecret(rootDir, consola, options = {}) {
501
+ const configuredSecret = options.configuredSecret?.trim();
502
+ if (configuredSecret)
503
+ return void 0;
504
+ if (process.env.NUXT_BETTER_AUTH_SECRET || process.env.BETTER_AUTH_SECRET || process.env.BETTER_AUTH_SECRETS || hasEnvSecret(rootDir))
505
+ return void 0;
506
+ const hasTty = Boolean(process.stdin.isTTY && process.stdout.isTTY);
507
+ if (options.prepare || !hasTty) {
508
+ consola.warn("[nuxt-better-auth] Skipping auth secret prompt (non-interactive). Set NUXT_BETTER_AUTH_SECRET, BETTER_AUTH_SECRET, or BETTER_AUTH_SECRETS.");
509
+ return void 0;
510
+ }
511
+ if (isCI || isTest) {
512
+ const secret2 = generateSecret();
513
+ appendSecretToEnv(rootDir, secret2);
514
+ consola.info("Generated NUXT_BETTER_AUTH_SECRET and added to .env (CI/test mode)");
515
+ return secret2;
516
+ }
517
+ consola.box("An auth secret is required for authentication.\nThis will add NUXT_BETTER_AUTH_SECRET to your .env file.\nBETTER_AUTH_SECRET and BETTER_AUTH_SECRETS are also supported.");
518
+ const choice = await consola.prompt("How do you want to set it?", {
519
+ type: "select",
520
+ options: [
521
+ { label: "Generate for me", value: "generate", hint: "uses crypto.randomBytes(32)" },
522
+ { label: "Enter manually", value: "paste" },
523
+ { label: "Skip", value: "skip", hint: "will fail in production" }
524
+ ],
525
+ cancel: "null"
526
+ });
527
+ if (typeof choice === "symbol" || choice === "skip") {
528
+ consola.warn("Skipping auth secret setup. Auth will fail without a configured secret in production.");
529
+ return void 0;
530
+ }
531
+ let secret;
532
+ if (choice === "generate") {
533
+ secret = generateSecret();
534
+ } else {
535
+ const input = await consola.prompt("Paste your secret (min 32 chars):", { type: "text", cancel: "null" });
536
+ if (typeof input === "symbol" || !input || input.length < 32) {
537
+ consola.warn("Invalid secret. Skipping.");
538
+ return void 0;
539
+ }
540
+ secret = input;
541
+ }
542
+ const preview = `${secret.slice(0, 8)}...${secret.slice(-4)}`;
543
+ const confirm = await consola.prompt(`Add to .env:
544
+ ${DEFAULT_SECRET_ENV}=${preview}
545
+ Proceed?`, { type: "confirm", initial: true, cancel: "null" });
546
+ if (typeof confirm === "symbol" || !confirm) {
547
+ consola.info("Cancelled. Secret not written.");
548
+ return void 0;
549
+ }
550
+ appendSecretToEnv(rootDir, secret);
551
+ consola.success("Added NUXT_BETTER_AUTH_SECRET to .env");
552
+ return secret;
553
+ }
554
+
555
+ function resolveDatabaseProvider(input) {
556
+ const enabledProviders = Object.entries(input.providers).filter(([_id, provider]) => provider.isEnabled?.(input.context) ?? true);
557
+ if (!enabledProviders.length) {
558
+ throw new Error("[nuxt-better-auth] No database provider is enabled. Register one with the better-auth:database:providers hook.");
559
+ }
560
+ enabledProviders.sort((a, b) => (b[1].priority ?? 0) - (a[1].priority ?? 0));
561
+ const [id, definition] = enabledProviders[0];
562
+ return { id, definition };
563
+ }
564
+
565
+ function resolveSecondaryStorage(input) {
566
+ const { options, clientOnly, hasNuxtHub, hub } = input;
567
+ const opt = options.hubSecondaryStorage ?? false;
568
+ const useHubKV = opt === true;
569
+ const secondaryStorageEnabled = opt === true || opt === "custom";
570
+ if (secondaryStorageEnabled && clientOnly) {
571
+ throw new Error("[nuxt-better-auth] hubSecondaryStorage is not available in clientOnly mode. Either disable clientOnly or remove auth.hubSecondaryStorage.");
572
+ }
573
+ if (useHubKV && (!hasNuxtHub || !hub?.kv)) {
574
+ throw new Error("[nuxt-better-auth] hubSecondaryStorage: true requires @nuxthub/core with hub.kv: true. Either add hub.kv: true to your nuxt.config or remove auth.hubSecondaryStorage.");
575
+ }
576
+ return { useHubKV, secondaryStorageEnabled };
577
+ }
578
+ function setupRuntimeConfig(input) {
579
+ const { nuxt, options, clientOnly, databaseProvider, consola } = input;
580
+ const { useHubKV, secondaryStorageEnabled } = resolveSecondaryStorage(input);
581
+ nuxt.options.runtimeConfig.public = nuxt.options.runtimeConfig.public || {};
582
+ const configuredSiteUrl = nuxt.options.runtimeConfig.public.siteUrl;
583
+ nuxt.options.runtimeConfig.public.siteUrl = configuredSiteUrl || process.env.NUXT_PUBLIC_SITE_URL || "";
584
+ nuxt.options.runtimeConfig.public.auth = defu(nuxt.options.runtimeConfig.public.auth, {
585
+ redirects: {
586
+ login: options.redirects?.login ?? "/login",
587
+ guest: options.redirects?.guest ?? "/",
588
+ authenticated: options.redirects?.authenticated,
589
+ logout: options.redirects?.logout
590
+ },
591
+ preserveRedirect: options.preserveRedirect ?? true,
592
+ redirectQueryKey: options.redirectQueryKey ?? "redirect",
593
+ useDatabase: databaseProvider !== "none",
594
+ databaseProvider,
595
+ clientOnly,
596
+ session: {
597
+ skipHydratedSsrGetSession: options.session?.skipHydratedSsrGetSession ?? false
598
+ }
599
+ });
600
+ if (clientOnly) {
601
+ const siteUrl = nuxt.options.runtimeConfig.public.siteUrl;
602
+ if (!siteUrl)
603
+ consola.warn("clientOnly mode: set runtimeConfig.public.siteUrl (or NUXT_PUBLIC_SITE_URL) to your frontend URL");
604
+ consola.info("clientOnly mode enabled - server utilities (serverAuth, getRequestSession, getUserSession, requireUserSession) are not available");
605
+ return { useHubKV, secondaryStorageEnabled };
606
+ }
607
+ const currentSecret = nuxt.options.runtimeConfig.betterAuthSecret;
608
+ nuxt.options.runtimeConfig.betterAuthSecret = currentSecret || process.env.NUXT_BETTER_AUTH_SECRET || process.env.BETTER_AUTH_SECRET || "";
609
+ nuxt.options.runtimeConfig.auth = defu(nuxt.options.runtimeConfig.auth, {
610
+ hubSecondaryStorage: options.hubSecondaryStorage ?? false
611
+ });
612
+ return { useHubKV, secondaryStorageEnabled };
613
+ }
614
+
615
+ function buildSecondaryStorageCode(useHubKV) {
616
+ if (!useHubKV)
617
+ return "export function createSecondaryStorage() { return undefined }";
618
+ return `import { kv } from '@nuxthub/kv'
619
+ export function createSecondaryStorage() {
620
+ return {
621
+ get: async (key) => kv.get(\`_auth:\${key}\`),
622
+ set: async (key, value, ttl) => kv.set(\`_auth:\${key}\`, value, { ttl }),
623
+ delete: async (key) => kv.del(\`_auth:\${key}\`),
624
+ }
625
+ }`;
626
+ }
627
+ function buildDatabaseCode(input) {
628
+ if (input.provider === "nuxthub") {
629
+ if (input.hubDialect === "postgresql") {
630
+ return `import { db } from '@nuxthub/db'
631
+ import * as schema from './schema.${input.hubDialect}.mjs'
632
+ import { drizzleAdapter } from 'better-auth/adapters/drizzle'
633
+ import { drizzle } from 'drizzle-orm/postgres-js'
634
+ import postgres from 'postgres'
635
+
636
+ const dialect = 'pg'
637
+ const requestDatabaseKey = Symbol.for('nuxt-better-auth.requestDatabase')
638
+ const fallbackRequestDatabaseContext = new WeakMap()
639
+
640
+ function getRequestDatabaseContext(event) {
641
+ const eventWithContext = event
642
+ if (eventWithContext?.context && typeof eventWithContext.context === 'object')
643
+ return eventWithContext.context
644
+
645
+ let context = fallbackRequestDatabaseContext.get(event)
646
+ if (!context) {
647
+ context = {}
648
+ fallbackRequestDatabaseContext.set(event, context)
649
+ }
650
+ return context
651
+ }
652
+
653
+ function createHyperdriveAdapter(client) {
654
+ return drizzleAdapter(drizzle({ client, schema }), { provider: dialect, schema, usePlural: ${input.usePlural}, camelCase: ${input.camelCase} })
655
+ }
656
+
657
+ function getCloudflareContext(event) {
658
+ return event?.context?.cloudflare
659
+ }
660
+
661
+ function resolveHyperdrive(event) {
662
+ const cloudflareEnv = getCloudflareContext(event)?.env
663
+ return cloudflareEnv?.POSTGRES || process.env.POSTGRES || globalThis.__env__?.POSTGRES || globalThis.POSTGRES
664
+ }
665
+
666
+ function scheduleCleanup(event, cleanup) {
667
+ const cloudflareContext = getCloudflareContext(event)
668
+ if (typeof cloudflareContext?.context?.waitUntil === 'function') {
669
+ cloudflareContext.context.waitUntil(cleanup)
670
+ return
671
+ }
672
+
673
+ if (typeof event?.context?.waitUntil === 'function') {
674
+ event.context.waitUntil(cleanup)
675
+ return
676
+ }
677
+
678
+ const waitUntil = event?.waitUntil || event?.req?.waitUntil || event?.node?.req?.waitUntil
679
+ if (typeof waitUntil === 'function')
680
+ waitUntil.call(event?.req || event?.node?.req || event, cleanup)
681
+ else
682
+ void cleanup
683
+ }
684
+
685
+ function registerClientCleanup(event, client) {
686
+ const response = event?.node?.res
687
+ if (!response || typeof response.once !== 'function')
688
+ return
689
+
690
+ let closed = false
691
+
692
+ const cleanup = () => {
693
+ if (closed)
694
+ return
695
+
696
+ closed = true
697
+ const close = client.end({ timeout: 0 }).catch(() => {})
698
+ scheduleCleanup(event, close)
699
+ }
700
+
701
+ response.once('finish', cleanup)
702
+ response.once('close', cleanup)
703
+ }
704
+
705
+ export function createDatabase(event) {
706
+ const hyperdrive = resolveHyperdrive(event)
707
+ if (!hyperdrive?.connectionString)
708
+ return drizzleAdapter(db, { provider: dialect, schema, usePlural: ${input.usePlural}, camelCase: ${input.camelCase} })
709
+
710
+ if (event) {
711
+ const context = getRequestDatabaseContext(event)
712
+ const cached = context[requestDatabaseKey]
713
+ if (cached)
714
+ return cached
715
+
716
+ const client = postgres(hyperdrive.connectionString, {
717
+ prepare: false,
718
+ onnotice: () => {},
719
+ max: 1,
720
+ })
721
+ const database = createHyperdriveAdapter(client)
722
+
723
+ context[requestDatabaseKey] = database
724
+ registerClientCleanup(event, client)
725
+ return database
726
+ }
727
+ const client = postgres(hyperdrive.connectionString, {
728
+ prepare: false,
729
+ onnotice: () => {},
730
+ max: 1,
731
+ })
732
+
733
+ return createHyperdriveAdapter(client)
734
+ }
735
+ export { db }`;
736
+ }
737
+ return `import { db } from '@nuxthub/db'
738
+ import * as schema from './schema.${input.hubDialect}.mjs'
739
+ import { drizzleAdapter } from 'better-auth/adapters/drizzle'
740
+ const rawDialect = '${input.hubDialect}'
741
+ const dialect = rawDialect === 'postgresql' ? 'pg' : rawDialect
742
+ export function createDatabase() { return drizzleAdapter(db, { provider: dialect, schema, usePlural: ${input.usePlural}, camelCase: ${input.camelCase} }) }
743
+ export { db }`;
744
+ }
745
+ return `export function createDatabase() { return undefined }
746
+ export const db = undefined`;
747
+ }
748
+ function buildSchemaExportCode(hasHubDb, hubDialect) {
749
+ if (!hasHubDb) {
750
+ return `export const user = undefined
751
+ export const session = undefined
752
+ export const account = undefined
753
+ export const verification = undefined
754
+ export const schema = undefined
755
+ `;
756
+ }
757
+ return `export * from './schema.${hubDialect}.mjs'
758
+ import * as generatedSchema from './schema.${hubDialect}.mjs'
759
+
760
+ const getGeneratedTable = name => generatedSchema[name] ?? generatedSchema[\`\${name}s\`]
761
+ export const user = getGeneratedTable('user')
762
+ export const session = getGeneratedTable('session')
763
+ export const account = getGeneratedTable('account')
764
+ export const verification = getGeneratedTable('verification')
765
+ export const schema = { ...generatedSchema, user, session, account, verification }
766
+ `;
767
+ }
768
+ function buildAuthRouteRulesCode(authRouteRules) {
769
+ return `export const authRouteRules = ${JSON.stringify(authRouteRules, null, 2)}
770
+ `;
771
+ }
772
+
773
+ function assertConfigPresence(configs, clientOnly) {
774
+ if (!clientOnly && !configs.server.exists)
775
+ throw new Error(`[nuxt-better-auth] Missing ${configs.server.file}.ts - export default defineServerAuth(...)`);
776
+ if (!configs.client.exists)
777
+ throw new Error(`[nuxt-better-auth] Missing ${configs.client.file}.ts - export default defineClientAuth(...)`);
778
+ }
779
+ function createDefaultDatabaseProviders(buildContext) {
780
+ return {
781
+ nuxthub: {
782
+ priority: 100,
783
+ isEnabled: ({ hasHubDbAvailable: enabled }) => enabled,
784
+ buildDatabaseCode: () => buildDatabaseCode({
785
+ provider: "nuxthub",
786
+ ...buildContext
787
+ })
788
+ },
789
+ none: {
790
+ priority: 0,
791
+ buildDatabaseCode: () => buildDatabaseCode({
792
+ provider: "none",
793
+ ...buildContext
794
+ })
795
+ }
796
+ };
797
+ }
798
+ function collectAuthRouteRules(nuxt) {
799
+ const runtimeRouteRulesSource = nuxt.options.nitro?.routeRules || nuxt.options.routeRules || {};
800
+ return Object.fromEntries(
801
+ Object.entries(runtimeRouteRulesSource).flatMap(([path, rule]) => {
802
+ if (!rule || typeof rule !== "object" || !("auth" in rule))
803
+ return [];
804
+ return [[path, { auth: rule.auth }]];
805
+ })
806
+ );
807
+ }
808
+ async function resolveAuthModuleSetup(input, dependencies = {}) {
809
+ const { nuxt, options, runtimeTypesAugmentPath, consola } = input;
810
+ const hasNuxtModuleFn = dependencies.hasNuxtModule ?? hasNuxtModule;
811
+ const clientOnly = options.clientOnly ?? false;
812
+ const configs = resolveAuthConfigDescriptors(nuxt, {
813
+ server: options.serverConfig,
814
+ client: options.clientConfig
815
+ }, {
816
+ configExists: dependencies.configExists
817
+ });
818
+ assertConfigPresence(configs, clientOnly);
819
+ const aliases = {
820
+ "#auth/server": clientOnly ? void 0 : configs.server.path,
821
+ "#auth/client": configs.client.path
822
+ };
823
+ if (aliases["#auth/server"])
824
+ nuxt.options.alias["#auth/server"] = aliases["#auth/server"];
825
+ nuxt.options.alias["#auth/client"] = aliases["#auth/client"];
826
+ const hasNuxtHub = hasNuxtModuleFn("@nuxthub/core", nuxt);
827
+ const hub = hasNuxtHub ? nuxt.options.hub : void 0;
828
+ const hasHubDbAvailable = !clientOnly && hasNuxtHub && !!hub?.db;
829
+ const hubDialect = getHubDialect(hub) ?? "sqlite";
830
+ const usePlural = options.schema?.usePlural ?? false;
831
+ const camelCase = (options.schema?.casing ?? getHubCasing(hub)) !== "snake_case";
832
+ let providerId = "none";
833
+ let providerDefinition;
834
+ if (!clientOnly) {
835
+ const buildContext = { hubDialect, usePlural, camelCase };
836
+ const providers = createDefaultDatabaseProviders(buildContext);
837
+ const enabledContext = {
838
+ nuxt,
839
+ options,
840
+ clientOnly,
841
+ hasHubDbAvailable
842
+ };
843
+ await nuxt.callHook("better-auth:database:providers", providers);
844
+ const resolvedProvider = resolveDatabaseProvider({
845
+ providers,
846
+ context: enabledContext
847
+ });
848
+ providerId = resolvedProvider.id;
849
+ providerDefinition = resolvedProvider.definition;
850
+ }
851
+ const runtime = setupRuntimeConfig({
852
+ nuxt,
853
+ options,
854
+ clientOnly,
855
+ databaseProvider: providerId,
856
+ hasNuxtHub,
857
+ hub,
858
+ consola
859
+ });
860
+ if (runtime.useHubKV && !nuxt.options.alias["hub:kv"]) {
861
+ throw new Error("[nuxt-better-auth] hub:kv not found. Ensure @nuxthub/core is loaded before this module and hub.kv is enabled.");
862
+ }
863
+ const hasHubDb = providerId === "nuxthub";
864
+ if (hasHubDb && !nuxt.options.alias["hub:db"]) {
865
+ throw new Error("[nuxt-better-auth] hub:db not found. Ensure @nuxthub/core is loaded before this module and hub.db is configured.");
866
+ }
867
+ return {
868
+ clientOnly,
869
+ configs,
870
+ aliases,
871
+ hub: {
872
+ hasNuxtHub,
873
+ options: hub,
874
+ hasHubDbAvailable
875
+ },
876
+ database: {
877
+ providerId,
878
+ hasHubDb,
879
+ providerDefinition,
880
+ buildContext: clientOnly ? void 0 : { hubDialect, usePlural, camelCase }
881
+ },
882
+ runtime,
883
+ prepareTypes: clientOnly ? void 0 : {
884
+ serverDir: dirname(configs.server.path),
885
+ hasHubDb
886
+ },
887
+ serverTypes: clientOnly ? void 0 : {
888
+ serverConfigPath: configs.server.path,
889
+ hasHubDb
890
+ },
891
+ sharedTypes: {
892
+ runtimeTypesAugmentPath,
893
+ clientConfigPath: configs.client.path
894
+ },
895
+ schemaGeneration: hasHubDb ? {
896
+ serverConfigPath: configs.server.path,
897
+ hubSecondaryStorage: options.hubSecondaryStorage ?? false,
898
+ externalizeNuxtHubDatabase: true
899
+ } : void 0
900
+ };
901
+ }
902
+
903
+ function registerServerTypeTemplates(input) {
904
+ const { serverConfigPath, hasHubDb, runtimeTypesPath, sharedServerConfigSafe, h3TypesPath, nitroTypesPath } = input;
905
+ const routeRuleAugmentations = (nitroTypesPath === "nitro/types" ? [nitroTypesPath] : ["nitropack", nitroTypesPath]).map((moduleName) => `declare module '${moduleName}' {
906
+ interface NitroRouteRules {
907
+ auth?: import('${runtimeTypesPath}').AuthMeta
908
+ }
909
+ interface NitroRouteConfig {
910
+ auth?: import('${runtimeTypesPath}').AuthMeta
911
+ }
912
+ }`).join("\n");
913
+ const serverConfigTypeTemplateOptions = sharedServerConfigSafe ? { nuxt: true, nitro: true, node: true, shared: true } : { nuxt: true, nitro: true, node: true };
914
+ addTypeTemplate({
915
+ filename: "types/auth-secondary-storage.d.ts",
916
+ getContents: () => `
917
+ declare module '#auth/secondary-storage' {
918
+ interface SecondaryStorage {
919
+ get: (key: string) => Promise<string | null>
920
+ set: (key: string, value: unknown, ttl?: number) => Promise<void>
921
+ delete: (key: string) => Promise<void>
922
+ }
923
+ export function createSecondaryStorage(): SecondaryStorage | undefined
924
+ }
925
+ `
926
+ }, { nitro: true });
927
+ addTypeTemplate({
928
+ filename: "types/auth-database.d.ts",
929
+ getContents: () => `
930
+ declare module '#auth/database' {
931
+ import type { BetterAuthOptions } from 'better-auth'
932
+ export function createDatabase(event?: import('${h3TypesPath}').H3Event): BetterAuthOptions['database']
933
+ export const db: ${hasHubDb ? `typeof import('@nuxthub/db')['db']` : "undefined"}
934
+ }
935
+ `
936
+ }, { nitro: true });
937
+ addTypeTemplate({
938
+ filename: "types/auth-schema.d.ts",
939
+ getContents: () => `
940
+ declare module '#auth/schema' {
941
+ export const user: any
942
+ export const session: any
943
+ export const account: any
944
+ export const verification: any
945
+ export const schema: {
946
+ user: any
947
+ session: any
948
+ account: any
949
+ verification: any
950
+ [key: string]: any
951
+ } | undefined
952
+ }
953
+ `
954
+ }, { nitro: true });
955
+ addTypeTemplate({
956
+ filename: "types/nuxt-better-auth-server-context.d.ts",
957
+ getContents: () => `
958
+ /// <reference path="./nitro-imports.d.ts" />
959
+ /// <reference path="./auth-database.d.ts" />
960
+ /// <reference path="./auth-schema.d.ts" />
961
+ /// <reference path="./auth-secondary-storage.d.ts" />
962
+ ${hasHubDb ? '/// <reference path="../hub/db.d.ts" />' : ""}
963
+
964
+ export {}
965
+ `
966
+ }, { node: true });
967
+ addTypeTemplate({
968
+ filename: "types/nuxt-better-auth-config-context.d.ts",
969
+ getContents: () => `
970
+ import type { RuntimeConfig } from 'nuxt/schema'
971
+
972
+ declare module '@nuxtjs/better-auth/config' {
973
+ interface ServerAuthContextExtension {
974
+ runtimeConfig: RuntimeConfig
975
+ db: ${hasHubDb ? `typeof import('@nuxthub/db')['db']` : "undefined"}
976
+ requestOrigin?: string
977
+ }
978
+ }
979
+
980
+ `
981
+ }, { nuxt: true, nitro: true, node: true, shared: true });
982
+ addTypeTemplate({
983
+ filename: "types/nuxt-better-auth-infer.d.ts",
984
+ getContents: () => `
985
+ import type { BetterAuthOptions, BetterAuthPlugin, InferPluginTypes, UnionToIntersection } from 'better-auth'
986
+ import type { InferFieldsOutput } from 'better-auth/db'
987
+ import type createServerAuth from '${serverConfigPath}'
988
+
989
+ type _RawConfig = ReturnType<typeof createServerAuth>
990
+ type _RawPlugins = _RawConfig extends { plugins: infer P } ? P : _RawConfig extends { plugins?: infer P } ? P : []
991
+ type _NormalizedPlugins = _RawPlugins extends readonly (infer T)[]
992
+ ? Array<T & BetterAuthPlugin>
993
+ : _RawPlugins extends (infer T)[]
994
+ ? Array<T & BetterAuthPlugin>
995
+ : BetterAuthPlugin[]
996
+ type _Config = Omit<BetterAuthOptions, 'plugins'> & Omit<_RawConfig, 'plugins'> & {
997
+ plugins?: _NormalizedPlugins
998
+ }
999
+
1000
+ type _InferModelFieldsFromPlugins<P, M extends string> = P extends readonly (infer Plugin)[]
1001
+ ? UnionToIntersection<Plugin extends { schema: { [K in M]: { fields: infer F } } } ? InferFieldsOutput<F> : {}>
1002
+ : P extends (infer Plugin)[]
1003
+ ? UnionToIntersection<Plugin extends { schema: { [K in M]: { fields: infer F } } } ? InferFieldsOutput<F> : {}>
1004
+ : {}
1005
+
1006
+ type _InferModelFieldsFromOptions<C, M extends 'user' | 'session'> = C extends { [K in M]: { additionalFields: infer F } }
1007
+ ? InferFieldsOutput<F>
1008
+ : {}
1009
+
1010
+ type _UserFallback = _InferModelFieldsFromPlugins<_RawPlugins, 'user'> & _InferModelFieldsFromOptions<_RawConfig, 'user'>
1011
+ type _SessionFallback = _InferModelFieldsFromPlugins<_RawPlugins, 'session'> & _InferModelFieldsFromOptions<_RawConfig, 'session'>
1012
+
1013
+ declare module '#nuxt-better-auth' {
1014
+ interface AuthUser extends _UserFallback {}
1015
+ interface AuthSession extends _SessionFallback {}
1016
+ type PluginTypes = InferPluginTypes<_Config>
1017
+ }
1018
+ `
1019
+ }, serverConfigTypeTemplateOptions);
1020
+ addTypeTemplate({
1021
+ filename: "types/nuxt-better-auth-social-providers.d.ts",
1022
+ getContents: () => `
1023
+ import type createServerAuth from '${serverConfigPath}'
1024
+
1025
+ type _RawConfig = ReturnType<typeof createServerAuth>
1026
+ type _RawSocialProviders = _RawConfig extends { socialProviders: infer S } ? S : _RawConfig extends { socialProviders?: infer S } ? S : {}
1027
+ type _SocialProviderIds = Extract<keyof NonNullable<_RawSocialProviders>, string>
1028
+
1029
+ declare module '#nuxt-better-auth' {
1030
+ interface AuthSocialProviderRegistry {
1031
+ ids: _SocialProviderIds
1032
+ }
1033
+ }
1034
+ `
1035
+ }, serverConfigTypeTemplateOptions);
1036
+ addTypeTemplate({
1037
+ filename: "types/nuxt-better-auth-endpoints.d.ts",
1038
+ getContents: () => `
1039
+ import type createServerAuth from '${serverConfigPath}'
1040
+ import type { BetterAuthOptions } from 'better-auth'
1041
+ import type { getEndpoints } from 'better-auth/api'
1042
+ import type { Serialize, Simplify } from '${nitroTypesPath}'
1043
+ import type { FetchError } from 'ofetch'
1044
+
1045
+ type _RawConfig = ReturnType<typeof createServerAuth>
1046
+ type _RawPlugins = _RawConfig extends { plugins: infer P } ? P : _RawConfig extends { plugins?: infer P } ? P : []
1047
+ type _Config = Omit<BetterAuthOptions, 'plugins'> & Omit<_RawConfig, 'plugins'> & {
1048
+ plugins?: _RawPlugins
1049
+ }
1050
+
1051
+ type _AuthApi = ReturnType<typeof getEndpoints<_Config>>['api']
1052
+ type _NormalizeMethod<M extends string> = M extends '*' ? 'default' : Lowercase<M>
1053
+ type _RouteMethodFromOption<M> = M extends readonly (infer T)[]
1054
+ ? _NormalizeMethod<Extract<T, string>>
1055
+ : M extends string
1056
+ ? _NormalizeMethod<M>
1057
+ : 'default'
1058
+ type _RouteMethodFromEndpoint<E> = E extends { options: { method: infer M } } ? _RouteMethodFromOption<M> : 'default'
1059
+ type _RoutePathFromEndpoint<E> = E extends { path: infer P extends string }
1060
+ ? string extends P
1061
+ ? never
1062
+ : \`/api/auth\${P}\`
1063
+ : never
1064
+ type _RouteResponseFromEndpoint<E> = E extends (...args: any[]) => Promise<infer R> ? Simplify<Serialize<Awaited<R>>> : never
1065
+ type _RouteDefaultResponse<E> = never
1066
+ type _UnionToIntersection<U> = (U extends unknown ? (value: U) => void : never) extends (value: infer I) => void ? I : never
1067
+
1068
+ type _CoreAuthInternalApi = {
1069
+ [K in keyof _AuthApi as _RoutePathFromEndpoint<_AuthApi[K]>]: {
1070
+ [M in _RouteMethodFromEndpoint<_AuthApi[K]> | 'default']: M extends 'default' ? _RouteDefaultResponse<_AuthApi[K]> : _RouteResponseFromEndpoint<_AuthApi[K]>
1071
+ }
1072
+ }
1073
+ type _PluginEndpointMaps<Plugins> = Plugins extends readonly (infer Plugin)[]
1074
+ ? Plugin extends { endpoints: infer Endpoints extends Record<string, unknown> }
1075
+ ? {
1076
+ [K in keyof Endpoints as _RoutePathFromEndpoint<Endpoints[K]>]: {
1077
+ [M in _RouteMethodFromEndpoint<Endpoints[K]> | 'default']: M extends 'default' ? _RouteDefaultResponse<Endpoints[K]> : _RouteResponseFromEndpoint<Endpoints[K]>
1078
+ }
1079
+ }
1080
+ : {}
1081
+ : Plugins extends (infer Plugin)[]
1082
+ ? Plugin extends { endpoints: infer Endpoints extends Record<string, unknown> }
1083
+ ? {
1084
+ [K in keyof Endpoints as _RoutePathFromEndpoint<Endpoints[K]>]: {
1085
+ [M in _RouteMethodFromEndpoint<Endpoints[K]> | 'default']: M extends 'default' ? _RouteDefaultResponse<Endpoints[K]> : _RouteResponseFromEndpoint<Endpoints[K]>
1086
+ }
1087
+ }
1088
+ : {}
1089
+ : {}
1090
+ type _PluginAuthInternalApi = _UnionToIntersection<_PluginEndpointMaps<_RawPlugins>>
1091
+ type _GeneratedAuthInternalApi = _CoreAuthInternalApi & _PluginAuthInternalApi
1092
+
1093
+ type _RoutePathToRequestPath<Path extends string> = Path extends \`\${infer Prefix}:\${string}/\${infer Rest}\`
1094
+ ? \`\${Prefix}\${string}/\${_RoutePathToRequestPath<Rest>}\`
1095
+ : Path extends \`\${infer Prefix}:\${string}\`
1096
+ ? \`\${Prefix}\${string}\`
1097
+ : Path
1098
+ type _AuthApiPatternPath = Extract<keyof _GeneratedAuthInternalApi, string>
1099
+ type _AuthApiRequestPath = _RoutePathToRequestPath<_AuthApiPatternPath>
1100
+ type _AuthPatternFromRequestPath<Path extends string> = {
1101
+ [Pattern in _AuthApiPatternPath]: Path extends _RoutePathToRequestPath<Pattern> ? Pattern : never
1102
+ }[_AuthApiPatternPath]
1103
+ type _AuthEndpointMethod<Path extends _AuthApiRequestPath> = Extract<keyof _GeneratedAuthInternalApi[_AuthPatternFromRequestPath<Path>], string>
1104
+
1105
+ type _AuthFetchMethod<Path extends _AuthApiRequestPath> = Extract<Exclude<import('${nitroTypesPath}').NitroFetchOptions<Path>['method'], undefined>, string>
1106
+ type _AuthFetchDefaultMethod<Path extends _AuthApiRequestPath> = 'get'
1107
+ type _AuthFetchResolvedMethod<Path extends _AuthApiRequestPath, Method extends string> = Lowercase<Method> extends _AuthEndpointMethod<Path>
1108
+ ? Lowercase<Method>
1109
+ : never
1110
+ type _AuthFetchResult<Path extends _AuthApiRequestPath, Method extends string> = _GeneratedAuthInternalApi[_AuthPatternFromRequestPath<Path>][_AuthFetchResolvedMethod<Path, Method>]
1111
+
1112
+ declare module '#nuxt-better-auth' {
1113
+ export type AuthApiInternalRoutes = _GeneratedAuthInternalApi
1114
+ export type AuthApiEndpointPatternPath = _AuthApiPatternPath
1115
+ export type AuthApiEndpointPath = _AuthApiRequestPath
1116
+ export type AuthApiEndpointMethod<Path extends AuthApiEndpointPath> = _AuthEndpointMethod<Path>
1117
+ export type AuthApiEndpointResponse<
1118
+ Path extends AuthApiEndpointPath,
1119
+ Method extends AuthApiEndpointMethod<Path> = AuthApiEndpointMethod<Path>,
1120
+ > = AuthApiInternalRoutes[_AuthPatternFromRequestPath<Path>][Method]
1121
+ }
1122
+
1123
+ declare module 'nuxt/dist/app/composables/fetch' {
1124
+ export function useFetch<
1125
+ ErrorT = FetchError,
1126
+ Path extends import('#nuxt-better-auth').AuthApiEndpointPath = import('#nuxt-better-auth').AuthApiEndpointPath,
1127
+ Method extends _AuthFetchMethod<Path> = _AuthFetchDefaultMethod<Path>,
1128
+ _ResT = _AuthFetchResult<Path, Method>,
1129
+ DataT = _ResT,
1130
+ PickKeys extends import('nuxt/dist/app/composables/asyncData').KeysOf<DataT> = import('nuxt/dist/app/composables/asyncData').KeysOf<DataT>,
1131
+ DefaultT = undefined,
1132
+ >(request: import('vue').Ref<Path> | Path | (() => Path), opts?: import('nuxt/dist/app/composables/fetch').UseFetchOptions<_ResT, DataT, PickKeys, DefaultT, Path, Method>): import('nuxt/dist/app/composables/asyncData').AsyncData<import('nuxt/dist/app/composables/asyncData').PickFrom<DataT, PickKeys> | DefaultT, ErrorT | undefined>
1133
+ export function useFetch<
1134
+ ErrorT = FetchError,
1135
+ Path extends import('#nuxt-better-auth').AuthApiEndpointPath = import('#nuxt-better-auth').AuthApiEndpointPath,
1136
+ Method extends _AuthFetchMethod<Path> = _AuthFetchDefaultMethod<Path>,
1137
+ _ResT = _AuthFetchResult<Path, Method>,
1138
+ DataT = _ResT,
1139
+ PickKeys extends import('nuxt/dist/app/composables/asyncData').KeysOf<DataT> = import('nuxt/dist/app/composables/asyncData').KeysOf<DataT>,
1140
+ DefaultT = DataT,
1141
+ >(request: import('vue').Ref<Path> | Path | (() => Path), opts?: import('nuxt/dist/app/composables/fetch').UseFetchOptions<_ResT, DataT, PickKeys, DefaultT, Path, Method>): import('nuxt/dist/app/composables/asyncData').AsyncData<import('nuxt/dist/app/composables/asyncData').PickFrom<DataT, PickKeys> | DefaultT, ErrorT | undefined>
1142
+ export function useFetch(request: string | import('vue').Ref<string> | (() => string), opts?: any): any
1143
+
1144
+ export function useLazyFetch<
1145
+ ErrorT = FetchError,
1146
+ Path extends import('#nuxt-better-auth').AuthApiEndpointPath = import('#nuxt-better-auth').AuthApiEndpointPath,
1147
+ Method extends _AuthFetchMethod<Path> = _AuthFetchDefaultMethod<Path>,
1148
+ _ResT = _AuthFetchResult<Path, Method>,
1149
+ DataT = _ResT,
1150
+ PickKeys extends import('nuxt/dist/app/composables/asyncData').KeysOf<DataT> = import('nuxt/dist/app/composables/asyncData').KeysOf<DataT>,
1151
+ DefaultT = undefined,
1152
+ >(request: import('vue').Ref<Path> | Path | (() => Path), opts?: Omit<import('nuxt/dist/app/composables/fetch').UseFetchOptions<_ResT, DataT, PickKeys, DefaultT, Path, Method>, 'lazy'>): import('nuxt/dist/app/composables/asyncData').AsyncData<import('nuxt/dist/app/composables/asyncData').PickFrom<DataT, PickKeys> | DefaultT, ErrorT | undefined>
1153
+ export function useLazyFetch<
1154
+ ErrorT = FetchError,
1155
+ Path extends import('#nuxt-better-auth').AuthApiEndpointPath = import('#nuxt-better-auth').AuthApiEndpointPath,
1156
+ Method extends _AuthFetchMethod<Path> = _AuthFetchDefaultMethod<Path>,
1157
+ _ResT = _AuthFetchResult<Path, Method>,
1158
+ DataT = _ResT,
1159
+ PickKeys extends import('nuxt/dist/app/composables/asyncData').KeysOf<DataT> = import('nuxt/dist/app/composables/asyncData').KeysOf<DataT>,
1160
+ DefaultT = DataT,
1161
+ >(request: import('vue').Ref<Path> | Path | (() => Path), opts?: Omit<import('nuxt/dist/app/composables/fetch').UseFetchOptions<_ResT, DataT, PickKeys, DefaultT, Path, Method>, 'lazy'>): import('nuxt/dist/app/composables/asyncData').AsyncData<import('nuxt/dist/app/composables/asyncData').PickFrom<DataT, PickKeys> | DefaultT, ErrorT | undefined>
1162
+ export function useLazyFetch(request: string | import('vue').Ref<string> | (() => string), opts?: any): any
1163
+ }
1164
+
1165
+ declare module 'nuxt/app' {
1166
+ export function useFetch<
1167
+ ErrorT = FetchError,
1168
+ Path extends import('#nuxt-better-auth').AuthApiEndpointPath = import('#nuxt-better-auth').AuthApiEndpointPath,
1169
+ Method extends _AuthFetchMethod<Path> = _AuthFetchDefaultMethod<Path>,
1170
+ _ResT = _AuthFetchResult<Path, Method>,
1171
+ DataT = _ResT,
1172
+ PickKeys extends import('nuxt/dist/app/composables/asyncData').KeysOf<DataT> = import('nuxt/dist/app/composables/asyncData').KeysOf<DataT>,
1173
+ DefaultT = undefined,
1174
+ >(request: import('vue').Ref<Path> | Path | (() => Path), opts?: import('nuxt/dist/app/composables/fetch').UseFetchOptions<_ResT, DataT, PickKeys, DefaultT, Path, Method>): import('nuxt/dist/app/composables/asyncData').AsyncData<import('nuxt/dist/app/composables/asyncData').PickFrom<DataT, PickKeys> | DefaultT, ErrorT | undefined>
1175
+ export function useFetch<
1176
+ ErrorT = FetchError,
1177
+ Path extends import('#nuxt-better-auth').AuthApiEndpointPath = import('#nuxt-better-auth').AuthApiEndpointPath,
1178
+ Method extends _AuthFetchMethod<Path> = _AuthFetchDefaultMethod<Path>,
1179
+ _ResT = _AuthFetchResult<Path, Method>,
1180
+ DataT = _ResT,
1181
+ PickKeys extends import('nuxt/dist/app/composables/asyncData').KeysOf<DataT> = import('nuxt/dist/app/composables/asyncData').KeysOf<DataT>,
1182
+ DefaultT = DataT,
1183
+ >(request: import('vue').Ref<Path> | Path | (() => Path), opts?: import('nuxt/dist/app/composables/fetch').UseFetchOptions<_ResT, DataT, PickKeys, DefaultT, Path, Method>): import('nuxt/dist/app/composables/asyncData').AsyncData<import('nuxt/dist/app/composables/asyncData').PickFrom<DataT, PickKeys> | DefaultT, ErrorT | undefined>
1184
+ export function useFetch(request: string | import('vue').Ref<string> | (() => string), opts?: any): any
1185
+
1186
+ export function useLazyFetch<
1187
+ ErrorT = FetchError,
1188
+ Path extends import('#nuxt-better-auth').AuthApiEndpointPath = import('#nuxt-better-auth').AuthApiEndpointPath,
1189
+ Method extends _AuthFetchMethod<Path> = _AuthFetchDefaultMethod<Path>,
1190
+ _ResT = _AuthFetchResult<Path, Method>,
1191
+ DataT = _ResT,
1192
+ PickKeys extends import('nuxt/dist/app/composables/asyncData').KeysOf<DataT> = import('nuxt/dist/app/composables/asyncData').KeysOf<DataT>,
1193
+ DefaultT = undefined,
1194
+ >(request: import('vue').Ref<Path> | Path | (() => Path), opts?: Omit<import('nuxt/dist/app/composables/fetch').UseFetchOptions<_ResT, DataT, PickKeys, DefaultT, Path, Method>, 'lazy'>): import('nuxt/dist/app/composables/asyncData').AsyncData<import('nuxt/dist/app/composables/asyncData').PickFrom<DataT, PickKeys> | DefaultT, ErrorT | undefined>
1195
+ export function useLazyFetch<
1196
+ ErrorT = FetchError,
1197
+ Path extends import('#nuxt-better-auth').AuthApiEndpointPath = import('#nuxt-better-auth').AuthApiEndpointPath,
1198
+ Method extends _AuthFetchMethod<Path> = _AuthFetchDefaultMethod<Path>,
1199
+ _ResT = _AuthFetchResult<Path, Method>,
1200
+ DataT = _ResT,
1201
+ PickKeys extends import('nuxt/dist/app/composables/asyncData').KeysOf<DataT> = import('nuxt/dist/app/composables/asyncData').KeysOf<DataT>,
1202
+ DefaultT = DataT,
1203
+ >(request: import('vue').Ref<Path> | Path | (() => Path), opts?: Omit<import('nuxt/dist/app/composables/fetch').UseFetchOptions<_ResT, DataT, PickKeys, DefaultT, Path, Method>, 'lazy'>): import('nuxt/dist/app/composables/asyncData').AsyncData<import('nuxt/dist/app/composables/asyncData').PickFrom<DataT, PickKeys> | DefaultT, ErrorT | undefined>
1204
+ export function useLazyFetch(request: string | import('vue').Ref<string> | (() => string), opts?: any): any
1205
+ }
1206
+ export {}
1207
+ `
1208
+ }, serverConfigTypeTemplateOptions);
1209
+ addTypeTemplate({
1210
+ filename: "types/nuxt-better-auth-nitro.d.ts",
1211
+ getContents: () => `
1212
+ ${routeRuleAugmentations}
1213
+ export {}
1214
+ `
1215
+ }, { nitro: true, node: true });
1216
+ }
1217
+ function registerSharedTypeTemplates(input) {
1218
+ const nitroV3 = input.h3TypesPath === "nitro/h3";
1219
+ addTypeTemplate({
1220
+ filename: "types/nuxt-better-auth.d.ts",
1221
+ getContents: () => `
1222
+ declare module '#nuxt-better-auth' {
1223
+ import type { ComputedRef, Ref } from 'vue'
1224
+
1225
+ export interface AuthUser {
1226
+ id: string
1227
+ createdAt: Date
1228
+ updatedAt: Date
1229
+ email: string
1230
+ emailVerified: boolean
1231
+ name: string
1232
+ image?: string | null
1233
+ }
1234
+
1235
+ export interface AuthSession {
1236
+ id: string
1237
+ createdAt: Date
1238
+ updatedAt: Date
1239
+ userId: string
1240
+ expiresAt: Date
1241
+ token: string
1242
+ ipAddress?: string | null
1243
+ userAgent?: string | null
1244
+ }
1245
+
1246
+ export interface ServerAuthContext {
1247
+ runtimeConfig: Record<string, unknown>
1248
+ db: unknown
1249
+ requestOrigin?: string
1250
+ }
1251
+
1252
+ export interface AuthSocialProviderRegistry {}
1253
+ export type AuthSocialProviderId = AuthSocialProviderRegistry extends { ids: infer T } ? Extract<T, string> : never
1254
+
1255
+ export interface UserSessionComposable {
1256
+ user: Ref<AuthUser | null>
1257
+ session: Ref<AuthSession | null>
1258
+ loggedIn: ComputedRef<boolean>
1259
+ ready: ComputedRef<boolean>
1260
+ fetchSession: (options?: { headers?: HeadersInit, force?: boolean }) => Promise<void>
1261
+ waitForSession: () => Promise<void>
1262
+ signOut: (options?: { onSuccess?: () => void | Promise<void> }) => Promise<void>
1263
+ updateUser: (updates: Partial<AuthUser>) => Promise<void>
1264
+ }
1265
+
1266
+ export type UserMatch<T> = { [K in keyof T]?: T[K] | T[K][] }
1267
+
1268
+ export interface AppSession {
1269
+ user: AuthUser
1270
+ session: AuthSession
1271
+ }
1272
+
1273
+ export interface RequireSessionOptions {
1274
+ user?: UserMatch<AuthUser>
1275
+ rule?: (ctx: { user: AuthUser, session: AuthSession }) => boolean | Promise<boolean>
1276
+ }
1277
+
1278
+ export type { AuthMeta, AuthMode, AuthRouteRules, Auth, InferUser, InferSession } from '${input.runtimeTypesPath}'
1279
+ }
1280
+ `
1281
+ }, { nuxt: true, nitro: true, node: true, shared: true });
1282
+ addTypeTemplate({
1283
+ filename: "types/nuxt-better-auth-h3.d.ts",
1284
+ getContents: () => `
1285
+ declare module '${nitroV3 ? "srvx" : "h3"}' {
1286
+ interface ${nitroV3 ? "ServerRequestContext" : "H3EventContext"} {
1287
+ requestSession?: import('${input.runtimeTypesAugmentPath}').AppSession | null
1288
+ }
1289
+ }
1290
+ export {}
1291
+ `
1292
+ }, { nuxt: true, nitro: true, node: true, shared: true });
1293
+ addTypeTemplate({
1294
+ filename: "types/nuxt-better-auth-client.d.ts",
1295
+ getContents: () => `
1296
+ import type createAppAuthClient from '${input.clientConfigPath}'
1297
+ declare module '#nuxt-better-auth' {
1298
+ export type AppAuthClient = ReturnType<typeof createAppAuthClient>
1299
+ }
1300
+ `
1301
+ });
1302
+ }
1303
+
1304
+ const consola = consola$1.withTag("nuxt-better-auth");
1305
+ const serverAliasImportRE = /from\s+['"]#server/;
1306
+ const layersAliasImportRE = /from\s+['"]#layers\//;
1307
+ const rootAliasImportRE = /from\s+['"]~~/;
1308
+ const workspaceAliasImportRE = /from\s+['"]@@/;
1309
+ const dbIdentifierRE = /\bdb\b/;
1310
+ const sessionHookAfterIdentifierRE = /\bsessionHookAfter\b/;
1311
+ const nuxtHubDbImportRE = /@nuxthub\/db/;
1312
+ function isServerConfigSharedTypeSafe(serverConfigPath) {
1313
+ const resolvedPath = [
1314
+ serverConfigPath,
1315
+ `${serverConfigPath}.ts`,
1316
+ `${serverConfigPath}.mts`,
1317
+ `${serverConfigPath}.cts`,
1318
+ `${serverConfigPath}.js`,
1319
+ `${serverConfigPath}.mjs`,
1320
+ `${serverConfigPath}.cjs`
1321
+ ].find((path) => existsSync(path));
1322
+ if (!resolvedPath)
1323
+ return false;
1324
+ const contents = readFileSync(resolvedPath, "utf8");
1325
+ return !(serverAliasImportRE.test(contents) || layersAliasImportRE.test(contents) || rootAliasImportRE.test(contents) || workspaceAliasImportRE.test(contents) || dbIdentifierRE.test(contents) || sessionHookAfterIdentifierRE.test(contents) || nuxtHubDbImportRE.test(contents));
1326
+ }
1327
+ async function createDefaultAuthConfigFiles(nuxt) {
1328
+ const configs = resolveAuthConfigDescriptors(nuxt);
1329
+ const serverTemplate = `import { defineServerAuth } from '@nuxtjs/better-auth/config'
1330
+
1331
+ export default defineServerAuth({
1332
+ emailAndPassword: { enabled: true },
1333
+ })
1334
+ `;
1335
+ const clientTemplate = `import { defineClientAuth } from '@nuxtjs/better-auth/config'
1336
+
1337
+ export default defineClientAuth({})
1338
+ `;
1339
+ if (configs.server.shouldCreateDefaultFile) {
1340
+ const serverPath = `${configs.server.path}.ts`;
1341
+ await mkdir(dirname(serverPath), { recursive: true });
1342
+ await writeFile(serverPath, serverTemplate);
1343
+ consola.success(`Created ${relative(configs.server.declaringLayerRoot, serverPath)}`);
1344
+ }
1345
+ if (configs.client.shouldCreateDefaultFile) {
1346
+ const clientPath = `${configs.client.path}.ts`;
1347
+ await mkdir(dirname(clientPath), { recursive: true });
1348
+ await writeFile(clientPath, clientTemplate);
1349
+ consola.success(`Created ${relative(configs.client.declaringLayerRoot, clientPath)}`);
1350
+ }
1351
+ }
1352
+ async function ensureSchemaBootstrap(schemaPath, dialect) {
1353
+ const dialectSchemaPath = join(dirname(schemaPath), `schema.${dialect}.mjs`);
1354
+ if (existsSync(schemaPath) && existsSync(dialectSchemaPath))
1355
+ return;
1356
+ await mkdir(dirname(schemaPath), { recursive: true });
1357
+ await writeFile(schemaPath, buildSchemaExportCode(false, dialect));
1358
+ }
1359
+ const module$1 = defineNuxtModule({
1360
+ meta: { name: "@nuxtjs/better-auth", version, configKey: "auth", compatibility: { nuxt: ">=4.0.0" } },
1361
+ defaults: {
1362
+ clientOnly: false,
1363
+ serverConfig: "server/auth.config",
1364
+ clientConfig: "app/auth.config",
1365
+ redirects: { login: "/login", guest: "/" },
1366
+ preserveRedirect: true,
1367
+ redirectQueryKey: "redirect",
1368
+ hubSecondaryStorage: false
1369
+ },
1370
+ async onInstall(nuxt) {
1371
+ const configuredSecret = nuxt.options.runtimeConfig?.betterAuthSecret;
1372
+ const generatedSecret = await promptForSecret(nuxt.options.rootDir, consola, { configuredSecret, prepare: Boolean(nuxt.options._prepare) });
1373
+ if (generatedSecret)
1374
+ process.env.NUXT_BETTER_AUTH_SECRET = generatedSecret;
1375
+ await createDefaultAuthConfigFiles(nuxt);
1376
+ },
1377
+ async setup(options, nuxt) {
1378
+ const resolver = createResolver(import.meta.url);
1379
+ const nitroImports = resolveNitroCompatibilityImports(nuxt._version);
1380
+ nuxt.options.alias["#better-auth/nitro-compat"] = resolver.resolve(`./runtime/server/internal/${nitroImports.runtime}`);
1381
+ const setup = await resolveAuthModuleSetup({
1382
+ nuxt,
1383
+ options,
1384
+ runtimeTypesAugmentPath: resolver.resolve("./runtime/types/augment"),
1385
+ consola
1386
+ });
1387
+ if (setup.aliases["#auth/server"])
1388
+ nuxt.options.alias["#auth/server"] = setup.aliases["#auth/server"];
1389
+ nuxt.options.alias["#auth/client"] = setup.aliases["#auth/client"];
1390
+ if (!setup.clientOnly) {
1391
+ const secondaryStorageTemplate = addTemplate({
1392
+ filename: "better-auth/secondary-storage.mjs",
1393
+ getContents: () => buildSecondaryStorageCode(setup.runtime.useHubKV),
1394
+ write: true
1395
+ });
1396
+ nuxt.options.alias["#auth/secondary-storage"] = secondaryStorageTemplate.dst;
1397
+ const databaseTemplate = addTemplate({
1398
+ filename: "better-auth/database.mjs",
1399
+ getContents: () => setup.database.providerDefinition.buildDatabaseCode(setup.database.buildContext),
1400
+ write: true
1401
+ });
1402
+ nuxt.options.alias["#auth/database"] = databaseTemplate.dst;
1403
+ const schemaTemplate = addTemplate({
1404
+ filename: "better-auth/schema.mjs",
1405
+ getContents: () => buildSchemaExportCode(setup.database.hasHubDb, setup.database.buildContext?.hubDialect ?? "sqlite"),
1406
+ write: true
1407
+ });
1408
+ nuxt.options.alias["#auth/schema"] = schemaTemplate.dst;
1409
+ if (setup.schemaGeneration)
1410
+ await ensureSchemaBootstrap(schemaTemplate.dst, setup.database.buildContext?.hubDialect ?? "sqlite");
1411
+ }
1412
+ if (setup.prepareTypes) {
1413
+ registerPrepareTypesHook({
1414
+ nuxt,
1415
+ serverDir: setup.prepareTypes.serverDir,
1416
+ hasHubDb: setup.prepareTypes.hasHubDb
1417
+ });
1418
+ }
1419
+ if (setup.database.providerDefinition) {
1420
+ const setupCtx = {
1421
+ nuxt,
1422
+ options,
1423
+ clientOnly: setup.clientOnly
1424
+ };
1425
+ await setup.database.providerDefinition.setup?.(setupCtx);
1426
+ }
1427
+ const authRouteRulesTemplate = addTemplate({
1428
+ filename: "better-auth/route-rules.mjs",
1429
+ getContents: () => buildAuthRouteRulesCode(collectAuthRouteRules(nuxt)),
1430
+ write: true
1431
+ });
1432
+ nuxt.options.alias["#auth/route-rules"] = authRouteRulesTemplate.dst;
1433
+ if (setup.serverTypes) {
1434
+ registerServerTypeTemplates({
1435
+ serverConfigPath: setup.serverTypes.serverConfigPath,
1436
+ hasHubDb: setup.serverTypes.hasHubDb,
1437
+ runtimeTypesPath: resolver.resolve("./runtime/types"),
1438
+ sharedServerConfigSafe: isServerConfigSharedTypeSafe(setup.serverTypes.serverConfigPath),
1439
+ h3TypesPath: nitroImports.h3,
1440
+ nitroTypesPath: nitroImports.types
1441
+ });
1442
+ }
1443
+ if (setup.schemaGeneration) {
1444
+ if (setup.schemaGeneration.externalizeNuxtHubDatabase)
1445
+ registerNuxtHubDatabaseExternalHook(nuxt);
1446
+ await setupBetterAuthSchema(
1447
+ nuxt,
1448
+ setup.schemaGeneration.serverConfigPath,
1449
+ options,
1450
+ consola,
1451
+ setup.schemaGeneration.hubSecondaryStorage
1452
+ );
1453
+ }
1454
+ registerSharedTypeTemplates({
1455
+ runtimeTypesAugmentPath: setup.sharedTypes.runtimeTypesAugmentPath,
1456
+ runtimeTypesPath: resolver.resolve("./runtime/types"),
1457
+ clientConfigPath: setup.sharedTypes.clientConfigPath,
1458
+ h3TypesPath: nitroImports.h3
1459
+ });
1460
+ registerTemplateHmrHook(nuxt);
1461
+ registerServerRuntime({ clientOnly: setup.clientOnly, resolve: resolver.resolve });
1462
+ registerAuthMiddlewareHook(nuxt, resolver.resolve);
1463
+ await registerDevtools({ nuxt, clientOnly: setup.clientOnly, hasHubDb: setup.database.hasHubDb, resolve: resolver.resolve });
1464
+ registerRouteRulesMetaHook(nuxt);
1465
+ }
1466
+ });
1467
+
1468
+ export { module$1 as default };