@onmax/nuxt-better-auth 0.0.2-alpha.30 → 0.0.2-alpha.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -17
- package/dist/module.d.mts +0 -9
- package/dist/module.json +2 -2
- package/dist/module.mjs +668 -267
- package/dist/runtime/app/components/BetterAuthState.d.vue.ts +4 -4
- package/dist/runtime/app/components/BetterAuthState.vue +1 -1
- package/dist/runtime/app/components/BetterAuthState.vue.d.ts +4 -4
- package/dist/runtime/app/composables/useAuthClient.d.ts +9 -0
- package/dist/runtime/app/composables/useAuthClient.js +34 -0
- package/dist/runtime/app/composables/useAuthClientAction.d.ts +1 -3
- package/dist/runtime/app/composables/useAuthClientAction.js +2 -2
- package/dist/runtime/app/composables/useAuthRequestFetch.d.ts +1 -1
- package/dist/runtime/app/composables/useSignIn.js +2 -2
- package/dist/runtime/app/composables/useSignUp.js +2 -2
- package/dist/runtime/app/composables/useUserSession.d.ts +5 -4
- package/dist/runtime/app/composables/useUserSession.js +91 -218
- package/dist/runtime/app/composables/useUserSessionState.d.ts +3 -0
- package/dist/runtime/app/composables/useUserSessionState.js +4 -0
- package/dist/runtime/app/internal/auth-action-error.js +1 -3
- package/dist/runtime/app/internal/auth-action-handles.js +1 -3
- package/dist/runtime/app/internal/redirect-helpers.d.ts +4 -0
- package/dist/runtime/app/internal/redirect-helpers.js +37 -0
- package/dist/runtime/app/internal/session-fetch.d.ts +12 -0
- package/dist/runtime/app/internal/session-fetch.js +56 -0
- package/dist/runtime/app/internal/utils.d.ts +1 -0
- package/dist/runtime/app/internal/utils.js +3 -0
- package/dist/runtime/app/internal/vue-safe-auth-proxy.d.ts +3 -0
- package/dist/runtime/app/internal/vue-safe-auth-proxy.js +68 -0
- package/dist/runtime/app/internal/wrap-auth-method.d.ts +15 -0
- package/dist/runtime/app/internal/wrap-auth-method.js +66 -0
- package/dist/runtime/app/middleware/auth.global.js +5 -4
- package/dist/runtime/app/plugins/session.client.js +2 -1
- package/dist/runtime/composables.d.ts +11 -0
- package/dist/runtime/composables.js +9 -0
- package/dist/runtime/config.d.ts +8 -6
- package/dist/runtime/config.js +3 -1
- package/dist/runtime/server/api/_better-auth/_schema.d.ts +1 -5
- package/dist/runtime/server/api/_better-auth/_schema.js +2 -1
- package/dist/runtime/server/api/_better-auth/accounts.get.d.ts +2 -2
- package/dist/runtime/server/api/_better-auth/config.get.js +1 -1
- package/dist/runtime/server/api/_better-auth/sessions.get.d.ts +2 -2
- package/dist/runtime/server/api/_better-auth/users.get.d.ts +2 -2
- package/dist/runtime/server/middleware/route-access.js +1 -1
- package/dist/runtime/server/utils/auth.d.ts +13 -2
- package/dist/runtime/server/utils/auth.js +42 -16
- package/dist/runtime/server/utils/session.d.ts +3 -1
- package/dist/runtime/server/utils/session.js +175 -1
- package/dist/runtime/server/virtual-modules.d.ts +5 -0
- package/dist/runtime/types/augment.d.ts +1 -3
- package/dist/runtime/types.d.ts +1 -1
- package/package.json +33 -26
package/dist/module.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { existsSync, writeFileSync, readFileSync } from 'node:fs';
|
|
1
|
+
import { existsSync, statSync, writeFileSync, readFileSync } from 'node:fs';
|
|
2
2
|
import { mkdir, writeFile } from 'node:fs/promises';
|
|
3
|
-
import { updateTemplates, addServerImportsDir, addServerImports, addServerScanDir, addServerHandler, addImportsDir, addPlugin, addComponentsDir, hasNuxtModule, installModule, extendPages, addTemplate, addTypeTemplate, defineNuxtModule, createResolver } from '@nuxt/kit';
|
|
3
|
+
import { getLayerDirectories, updateTemplates, addServerImportsDir, addServerImports, addServerScanDir, addServerHandler, addImportsDir, addPlugin, addComponentsDir, hasNuxtModule, installModule, extendPages, addTemplate, addTypeTemplate, defineNuxtModule, createResolver } from '@nuxt/kit';
|
|
4
4
|
import { consola as consola$1 } from 'consola';
|
|
5
|
-
import { join, dirname } from 'pathe';
|
|
5
|
+
import { isAbsolute, join, relative, dirname } from 'pathe';
|
|
6
6
|
import { defu } from 'defu';
|
|
7
7
|
import { toRouteMatcher, createRouter } from 'radix3';
|
|
8
8
|
import { generateDrizzleSchema as generateDrizzleSchema$1 } from '@better-auth/cli/api';
|
|
@@ -10,16 +10,120 @@ import { randomBytes } from 'node:crypto';
|
|
|
10
10
|
import { isCI, isTest } from 'std-env';
|
|
11
11
|
export { defineClientAuth, defineServerAuth } from '../dist/runtime/config.js';
|
|
12
12
|
|
|
13
|
-
const version = "0.0.2-alpha.
|
|
13
|
+
const version = "0.0.2-alpha.32";
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
+
}
|
|
19
52
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
+
};
|
|
23
127
|
}
|
|
24
128
|
|
|
25
129
|
function setupDevTools(nuxt) {
|
|
@@ -64,6 +168,57 @@ function registerAuthMiddlewareHook(nuxt, resolve) {
|
|
|
64
168
|
app.middleware.push({ name: "auth", path: resolve("./runtime/app/middleware/auth.global"), global: true });
|
|
65
169
|
});
|
|
66
170
|
}
|
|
171
|
+
function registerPrepareTypesHook(input) {
|
|
172
|
+
const { nuxt, serverDir, hasHubDb } = input;
|
|
173
|
+
nuxt.hook("prepare:types", ({ nodeTsConfig, nodeReferences, sharedReferences }) => {
|
|
174
|
+
nodeTsConfig.compilerOptions ||= {};
|
|
175
|
+
nodeTsConfig.compilerOptions.paths ||= {};
|
|
176
|
+
const projectReferenceTypePaths = [
|
|
177
|
+
join(nuxt.options.buildDir, "types/nitro-imports.d.ts"),
|
|
178
|
+
join(nuxt.options.buildDir, "types/auth-database.d.ts"),
|
|
179
|
+
join(nuxt.options.buildDir, "types/auth-schema.d.ts"),
|
|
180
|
+
join(nuxt.options.buildDir, "types/auth-secondary-storage.d.ts")
|
|
181
|
+
];
|
|
182
|
+
if (hasHubDb)
|
|
183
|
+
projectReferenceTypePaths.push(join(nuxt.options.buildDir, "hub/db.d.ts"));
|
|
184
|
+
const exactNodeAliases = {
|
|
185
|
+
"#server": serverDir,
|
|
186
|
+
"#auth/server": nuxt.options.alias["#auth/server"],
|
|
187
|
+
"#auth/client": nuxt.options.alias["#auth/client"],
|
|
188
|
+
"#auth/database": nuxt.options.alias["#auth/database"],
|
|
189
|
+
"#auth/schema": nuxt.options.alias["#auth/schema"],
|
|
190
|
+
"#auth/secondary-storage": nuxt.options.alias["#auth/secondary-storage"],
|
|
191
|
+
"#auth/route-rules": nuxt.options.alias["#auth/route-rules"],
|
|
192
|
+
"#nuxt-better-auth": nuxt.options.alias["#nuxt-better-auth"]
|
|
193
|
+
};
|
|
194
|
+
for (const [key, value] of Object.entries(exactNodeAliases)) {
|
|
195
|
+
if (typeof value === "string")
|
|
196
|
+
nodeTsConfig.compilerOptions.paths[key] = [value];
|
|
197
|
+
}
|
|
198
|
+
for (const [key, value] of Object.entries(nuxt.options.alias)) {
|
|
199
|
+
if (typeof value !== "string" || !isAbsolute(value))
|
|
200
|
+
continue;
|
|
201
|
+
nodeTsConfig.compilerOptions.paths[key] ||= [value];
|
|
202
|
+
if (!key.includes("*") && existsSync(value) && statSync(value).isDirectory())
|
|
203
|
+
nodeTsConfig.compilerOptions.paths[`${key}/*`] ||= [join(value, "*")];
|
|
204
|
+
}
|
|
205
|
+
nodeTsConfig.compilerOptions.paths["#server/*"] = [join(serverDir, "*")];
|
|
206
|
+
for (const path of projectReferenceTypePaths) {
|
|
207
|
+
if (!nodeReferences.some((reference) => "path" in reference && reference.path === path))
|
|
208
|
+
nodeReferences.push({ path });
|
|
209
|
+
if (!sharedReferences.some((reference) => "path" in reference && reference.path === path))
|
|
210
|
+
sharedReferences.push({ path });
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
function registerNuxtHubDatabaseExternalHook(nuxt) {
|
|
215
|
+
nuxt.hook("nitro:config", (nitroConfig) => {
|
|
216
|
+
nitroConfig.externals ||= {};
|
|
217
|
+
nitroConfig.externals.external ||= [];
|
|
218
|
+
if (!nitroConfig.externals.external.includes("@nuxthub/db"))
|
|
219
|
+
nitroConfig.externals.external.push("@nuxthub/db");
|
|
220
|
+
});
|
|
221
|
+
}
|
|
67
222
|
async function registerDevtools(input) {
|
|
68
223
|
const { nuxt, clientOnly, hasHubDb, resolve } = input;
|
|
69
224
|
const isProduction = process.env.NODE_ENV === "production" || !nuxt.options.dev;
|
|
@@ -108,79 +263,6 @@ function registerRouteRulesMetaHook(nuxt) {
|
|
|
108
263
|
});
|
|
109
264
|
}
|
|
110
265
|
|
|
111
|
-
function getHubDialect(hub) {
|
|
112
|
-
if (!hub?.db)
|
|
113
|
-
return void 0;
|
|
114
|
-
if (typeof hub.db === "string")
|
|
115
|
-
return hub.db;
|
|
116
|
-
if (typeof hub.db === "object" && hub.db !== null)
|
|
117
|
-
return hub.db.dialect;
|
|
118
|
-
return void 0;
|
|
119
|
-
}
|
|
120
|
-
function getHubCasing(hub) {
|
|
121
|
-
if (!hub?.db || typeof hub.db !== "object" || hub.db === null)
|
|
122
|
-
return void 0;
|
|
123
|
-
return hub.db.casing;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function resolveSecondaryStorage(input) {
|
|
127
|
-
const { options, clientOnly, hasNuxtHub, hub } = input;
|
|
128
|
-
const opt = options.hubSecondaryStorage ?? false;
|
|
129
|
-
const useHubKV = opt === true;
|
|
130
|
-
const secondaryStorageEnabled = opt === true || opt === "custom";
|
|
131
|
-
if (secondaryStorageEnabled && clientOnly) {
|
|
132
|
-
throw new Error("[nuxt-better-auth] hubSecondaryStorage is not available in clientOnly mode. Either disable clientOnly or remove auth.hubSecondaryStorage.");
|
|
133
|
-
}
|
|
134
|
-
if (useHubKV && (!hasNuxtHub || !hub?.kv)) {
|
|
135
|
-
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.");
|
|
136
|
-
}
|
|
137
|
-
return { useHubKV, secondaryStorageEnabled };
|
|
138
|
-
}
|
|
139
|
-
function setupRuntimeConfig(input) {
|
|
140
|
-
const { nuxt, options, clientOnly, databaseProvider, consola } = input;
|
|
141
|
-
const { useHubKV, secondaryStorageEnabled } = resolveSecondaryStorage(input);
|
|
142
|
-
nuxt.options.runtimeConfig.public = nuxt.options.runtimeConfig.public || {};
|
|
143
|
-
const configuredSiteUrl = nuxt.options.runtimeConfig.public.siteUrl;
|
|
144
|
-
if (!configuredSiteUrl && process.env.NUXT_PUBLIC_SITE_URL)
|
|
145
|
-
nuxt.options.runtimeConfig.public.siteUrl = process.env.NUXT_PUBLIC_SITE_URL;
|
|
146
|
-
nuxt.options.runtimeConfig.public.auth = defu(nuxt.options.runtimeConfig.public.auth, {
|
|
147
|
-
redirects: {
|
|
148
|
-
login: options.redirects?.login ?? "/login",
|
|
149
|
-
guest: options.redirects?.guest ?? "/",
|
|
150
|
-
authenticated: options.redirects?.authenticated,
|
|
151
|
-
logout: options.redirects?.logout
|
|
152
|
-
},
|
|
153
|
-
preserveRedirect: options.preserveRedirect ?? true,
|
|
154
|
-
redirectQueryKey: options.redirectQueryKey ?? "redirect",
|
|
155
|
-
useDatabase: databaseProvider !== "none",
|
|
156
|
-
databaseProvider,
|
|
157
|
-
clientOnly,
|
|
158
|
-
session: {
|
|
159
|
-
skipHydratedSsrGetSession: options.session?.skipHydratedSsrGetSession ?? false
|
|
160
|
-
}
|
|
161
|
-
});
|
|
162
|
-
if (clientOnly) {
|
|
163
|
-
const siteUrl = nuxt.options.runtimeConfig.public.siteUrl;
|
|
164
|
-
if (!siteUrl)
|
|
165
|
-
consola.warn("clientOnly mode: set runtimeConfig.public.siteUrl (or NUXT_PUBLIC_SITE_URL) to your frontend URL");
|
|
166
|
-
consola.info("clientOnly mode enabled - server utilities (serverAuth, getRequestSession, getUserSession, requireUserSession) are not available");
|
|
167
|
-
return { useHubKV, secondaryStorageEnabled };
|
|
168
|
-
}
|
|
169
|
-
const currentSecret = nuxt.options.runtimeConfig.betterAuthSecret;
|
|
170
|
-
nuxt.options.runtimeConfig.betterAuthSecret = currentSecret || process.env.BETTER_AUTH_SECRET || "";
|
|
171
|
-
const betterAuthSecret = nuxt.options.runtimeConfig.betterAuthSecret;
|
|
172
|
-
if (!nuxt.options.dev && !nuxt.options._prepare && !betterAuthSecret) {
|
|
173
|
-
throw new Error("[nuxt-better-auth] BETTER_AUTH_SECRET is required in production. Set BETTER_AUTH_SECRET or NUXT_BETTER_AUTH_SECRET environment variable.");
|
|
174
|
-
}
|
|
175
|
-
if (betterAuthSecret && betterAuthSecret.length < 32) {
|
|
176
|
-
throw new Error("[nuxt-better-auth] BETTER_AUTH_SECRET must be at least 32 characters for security");
|
|
177
|
-
}
|
|
178
|
-
nuxt.options.runtimeConfig.auth = defu(nuxt.options.runtimeConfig.auth, {
|
|
179
|
-
hubSecondaryStorage: options.hubSecondaryStorage ?? false
|
|
180
|
-
});
|
|
181
|
-
return { useHubKV, secondaryStorageEnabled };
|
|
182
|
-
}
|
|
183
|
-
|
|
184
266
|
function dialectToProvider(dialect) {
|
|
185
267
|
return dialect === "postgresql" ? "pg" : dialect;
|
|
186
268
|
}
|
|
@@ -213,18 +295,19 @@ async function generateDrizzleSchema(authOptions, dialect, schemaOptions) {
|
|
|
213
295
|
}
|
|
214
296
|
return result.code;
|
|
215
297
|
}
|
|
216
|
-
async function loadUserAuthConfig(configPath, throwOnError = false) {
|
|
298
|
+
async function loadUserAuthConfig(configPath, throwOnError = false, alias) {
|
|
217
299
|
const { createJiti } = await import('jiti');
|
|
218
300
|
const { defineServerAuth: runtimeDefineServerAuth } = await import('../dist/runtime/config.js');
|
|
219
|
-
const jiti = createJiti(import.meta.url, { interopDefault: true, moduleCache: false });
|
|
220
|
-
|
|
301
|
+
const jiti = createJiti(import.meta.url, { interopDefault: true, moduleCache: false, alias });
|
|
302
|
+
const schemaGlobals = globalThis;
|
|
303
|
+
if (!schemaGlobals.__nuxtBetterAuthDefineServerAuth) {
|
|
221
304
|
runtimeDefineServerAuth._count = 0;
|
|
222
|
-
|
|
305
|
+
schemaGlobals.__nuxtBetterAuthDefineServerAuth = runtimeDefineServerAuth;
|
|
223
306
|
}
|
|
224
|
-
if (!
|
|
225
|
-
|
|
307
|
+
if (!schemaGlobals.defineServerAuth) {
|
|
308
|
+
schemaGlobals.defineServerAuth = schemaGlobals.__nuxtBetterAuthDefineServerAuth;
|
|
226
309
|
}
|
|
227
|
-
|
|
310
|
+
schemaGlobals.__nuxtBetterAuthDefineServerAuth._count++;
|
|
228
311
|
try {
|
|
229
312
|
const mod = await jiti.import(configPath);
|
|
230
313
|
const configFn = mod.default;
|
|
@@ -243,19 +326,35 @@ async function loadUserAuthConfig(configPath, throwOnError = false) {
|
|
|
243
326
|
consola$1.error("[@onmax/nuxt-better-auth] Failed to load auth config for schema generation. Schema may be incomplete:", error);
|
|
244
327
|
return {};
|
|
245
328
|
} finally {
|
|
246
|
-
const sharedDefineServerAuth =
|
|
329
|
+
const sharedDefineServerAuth = schemaGlobals.__nuxtBetterAuthDefineServerAuth;
|
|
247
330
|
if (sharedDefineServerAuth) {
|
|
248
331
|
sharedDefineServerAuth._count--;
|
|
249
332
|
if (!sharedDefineServerAuth._count) {
|
|
250
|
-
|
|
251
|
-
if (
|
|
252
|
-
|
|
333
|
+
schemaGlobals.__nuxtBetterAuthDefineServerAuth = void 0;
|
|
334
|
+
if (schemaGlobals.defineServerAuth === sharedDefineServerAuth) {
|
|
335
|
+
schemaGlobals.defineServerAuth = void 0;
|
|
253
336
|
}
|
|
254
337
|
}
|
|
255
338
|
}
|
|
256
339
|
}
|
|
257
340
|
}
|
|
258
341
|
|
|
342
|
+
function getHubDialect(hub) {
|
|
343
|
+
if (!hub?.db)
|
|
344
|
+
return void 0;
|
|
345
|
+
if (typeof hub.db === "string")
|
|
346
|
+
return hub.db;
|
|
347
|
+
if (typeof hub.db === "object" && hub.db !== null)
|
|
348
|
+
return hub.db.dialect;
|
|
349
|
+
return void 0;
|
|
350
|
+
}
|
|
351
|
+
function getHubCasing(hub) {
|
|
352
|
+
if (!hub?.db || typeof hub.db !== "object" || hub.db === null)
|
|
353
|
+
return void 0;
|
|
354
|
+
return hub.db.casing;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const NODE_MODULES_SEGMENT_RE = /[\\/]/;
|
|
259
358
|
function resolveSchemaSecondaryStorageInjection(hubSecondaryStorage, userHasSecondaryStorage, isProduction) {
|
|
260
359
|
if (hubSecondaryStorage === true)
|
|
261
360
|
return { inject: false };
|
|
@@ -269,7 +368,7 @@ function resolveSchemaSecondaryStorageInjection(hubSecondaryStorage, userHasSeco
|
|
|
269
368
|
return { inject: false, warn: message };
|
|
270
369
|
}
|
|
271
370
|
function isInsideNodeModules(path) {
|
|
272
|
-
return path.split(
|
|
371
|
+
return path.split(NODE_MODULES_SEGMENT_RE).includes("node_modules");
|
|
273
372
|
}
|
|
274
373
|
function resolveHubSchemaPath(buildDir, rootDir, dialect, exists = existsSync) {
|
|
275
374
|
const rootTsPath = join(rootDir, ".nuxt", "better-auth", `schema.${dialect}.ts`);
|
|
@@ -286,7 +385,10 @@ function resolveHubSchemaPath(buildDir, rootDir, dialect, exists = existsSync) {
|
|
|
286
385
|
async function loadAuthOptions(context) {
|
|
287
386
|
const isProduction = !context.nuxt.options.dev;
|
|
288
387
|
const configFile = `${context.serverConfigPath}.ts`;
|
|
289
|
-
const
|
|
388
|
+
const alias = Object.fromEntries(
|
|
389
|
+
Object.entries(context.nuxt.options.alias).filter(([, value]) => typeof value === "string").map(([key, value]) => [key, value])
|
|
390
|
+
);
|
|
391
|
+
const userConfig = await loadUserAuthConfig(configFile, isProduction, alias);
|
|
290
392
|
const extendedConfig = {};
|
|
291
393
|
await context.nuxt.callHook("better-auth:config:extend", extendedConfig);
|
|
292
394
|
const plugins = [...userConfig.plugins || [], ...extendedConfig.plugins || []];
|
|
@@ -348,21 +450,26 @@ async function setupBetterAuthSchema(nuxt, serverConfigPath, options, consola, h
|
|
|
348
450
|
}
|
|
349
451
|
}
|
|
350
452
|
|
|
453
|
+
const DEFAULT_SECRET_ENV = "NUXT_BETTER_AUTH_SECRET";
|
|
454
|
+
const FALLBACK_SECRET_ENV = "BETTER_AUTH_SECRET";
|
|
351
455
|
const generateSecret = () => randomBytes(32).toString("hex");
|
|
352
456
|
function readEnvFile(rootDir) {
|
|
353
457
|
const envPath = join(rootDir, ".env");
|
|
354
458
|
return existsSync(envPath) ? readFileSync(envPath, "utf-8") : "";
|
|
355
459
|
}
|
|
356
460
|
function hasEnvSecret(rootDir) {
|
|
357
|
-
const
|
|
358
|
-
return
|
|
461
|
+
const envFile = readEnvFile(rootDir);
|
|
462
|
+
return [DEFAULT_SECRET_ENV, FALLBACK_SECRET_ENV].some((name) => {
|
|
463
|
+
const match = envFile.match(new RegExp(`^${name}=(.+)$`, "m"));
|
|
464
|
+
return !!match && !!match[1] && match[1].trim().length > 0;
|
|
465
|
+
});
|
|
359
466
|
}
|
|
360
467
|
function appendSecretToEnv(rootDir, secret) {
|
|
361
468
|
const envPath = join(rootDir, ".env");
|
|
362
469
|
let content = readEnvFile(rootDir);
|
|
363
470
|
if (content.length > 0 && !content.endsWith("\n"))
|
|
364
471
|
content += "\n";
|
|
365
|
-
content +=
|
|
472
|
+
content += `${DEFAULT_SECRET_ENV}=${secret}
|
|
366
473
|
`;
|
|
367
474
|
writeFileSync(envPath, content, "utf-8");
|
|
368
475
|
}
|
|
@@ -370,20 +477,20 @@ async function promptForSecret(rootDir, consola, options = {}) {
|
|
|
370
477
|
const configuredSecret = options.configuredSecret?.trim();
|
|
371
478
|
if (configuredSecret)
|
|
372
479
|
return void 0;
|
|
373
|
-
if (process.env.BETTER_AUTH_SECRET || hasEnvSecret(rootDir))
|
|
480
|
+
if (process.env.NUXT_BETTER_AUTH_SECRET || process.env.BETTER_AUTH_SECRET || hasEnvSecret(rootDir))
|
|
374
481
|
return void 0;
|
|
375
482
|
const hasTty = Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
376
483
|
if (options.prepare || !hasTty) {
|
|
377
|
-
consola.warn("[nuxt-better-auth] Skipping
|
|
484
|
+
consola.warn("[nuxt-better-auth] Skipping NUXT_BETTER_AUTH_SECRET prompt (non-interactive). Set NUXT_BETTER_AUTH_SECRET or BETTER_AUTH_SECRET.");
|
|
378
485
|
return void 0;
|
|
379
486
|
}
|
|
380
487
|
if (isCI || isTest) {
|
|
381
488
|
const secret2 = generateSecret();
|
|
382
489
|
appendSecretToEnv(rootDir, secret2);
|
|
383
|
-
consola.info("Generated
|
|
490
|
+
consola.info("Generated NUXT_BETTER_AUTH_SECRET and added to .env (CI/test mode)");
|
|
384
491
|
return secret2;
|
|
385
492
|
}
|
|
386
|
-
consola.box("
|
|
493
|
+
consola.box("NUXT_BETTER_AUTH_SECRET is required for authentication.\nThis will be appended to your .env file.\nBETTER_AUTH_SECRET is still supported as a fallback.");
|
|
387
494
|
const choice = await consola.prompt("How do you want to set it?", {
|
|
388
495
|
type: "select",
|
|
389
496
|
options: [
|
|
@@ -394,7 +501,7 @@ async function promptForSecret(rootDir, consola, options = {}) {
|
|
|
394
501
|
cancel: "null"
|
|
395
502
|
});
|
|
396
503
|
if (typeof choice === "symbol" || choice === "skip") {
|
|
397
|
-
consola.warn("Skipping
|
|
504
|
+
consola.warn("Skipping NUXT_BETTER_AUTH_SECRET. Auth will fail without it in production.");
|
|
398
505
|
return void 0;
|
|
399
506
|
}
|
|
400
507
|
let secret;
|
|
@@ -410,17 +517,85 @@ async function promptForSecret(rootDir, consola, options = {}) {
|
|
|
410
517
|
}
|
|
411
518
|
const preview = `${secret.slice(0, 8)}...${secret.slice(-4)}`;
|
|
412
519
|
const confirm = await consola.prompt(`Add to .env:
|
|
413
|
-
|
|
520
|
+
${DEFAULT_SECRET_ENV}=${preview}
|
|
414
521
|
Proceed?`, { type: "confirm", initial: true, cancel: "null" });
|
|
415
522
|
if (typeof confirm === "symbol" || !confirm) {
|
|
416
523
|
consola.info("Cancelled. Secret not written.");
|
|
417
524
|
return void 0;
|
|
418
525
|
}
|
|
419
526
|
appendSecretToEnv(rootDir, secret);
|
|
420
|
-
consola.success("Added
|
|
527
|
+
consola.success("Added NUXT_BETTER_AUTH_SECRET to .env");
|
|
421
528
|
return secret;
|
|
422
529
|
}
|
|
423
530
|
|
|
531
|
+
function resolveDatabaseProvider(input) {
|
|
532
|
+
const enabledProviders = Object.entries(input.providers).filter(([_id, provider]) => provider.isEnabled?.(input.context) ?? true);
|
|
533
|
+
if (!enabledProviders.length) {
|
|
534
|
+
throw new Error("[nuxt-better-auth] No database provider is enabled. Register one with the better-auth:database:providers hook.");
|
|
535
|
+
}
|
|
536
|
+
enabledProviders.sort((a, b) => (b[1].priority ?? 0) - (a[1].priority ?? 0));
|
|
537
|
+
const [id, definition] = enabledProviders[0];
|
|
538
|
+
return { id, definition };
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
function resolveSecondaryStorage(input) {
|
|
542
|
+
const { options, clientOnly, hasNuxtHub, hub } = input;
|
|
543
|
+
const opt = options.hubSecondaryStorage ?? false;
|
|
544
|
+
const useHubKV = opt === true;
|
|
545
|
+
const secondaryStorageEnabled = opt === true || opt === "custom";
|
|
546
|
+
if (secondaryStorageEnabled && clientOnly) {
|
|
547
|
+
throw new Error("[nuxt-better-auth] hubSecondaryStorage is not available in clientOnly mode. Either disable clientOnly or remove auth.hubSecondaryStorage.");
|
|
548
|
+
}
|
|
549
|
+
if (useHubKV && (!hasNuxtHub || !hub?.kv)) {
|
|
550
|
+
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.");
|
|
551
|
+
}
|
|
552
|
+
return { useHubKV, secondaryStorageEnabled };
|
|
553
|
+
}
|
|
554
|
+
function setupRuntimeConfig(input) {
|
|
555
|
+
const { nuxt, options, clientOnly, databaseProvider, consola } = input;
|
|
556
|
+
const { useHubKV, secondaryStorageEnabled } = resolveSecondaryStorage(input);
|
|
557
|
+
nuxt.options.runtimeConfig.public = nuxt.options.runtimeConfig.public || {};
|
|
558
|
+
const configuredSiteUrl = nuxt.options.runtimeConfig.public.siteUrl;
|
|
559
|
+
if (!configuredSiteUrl && process.env.NUXT_PUBLIC_SITE_URL)
|
|
560
|
+
nuxt.options.runtimeConfig.public.siteUrl = process.env.NUXT_PUBLIC_SITE_URL;
|
|
561
|
+
nuxt.options.runtimeConfig.public.auth = defu(nuxt.options.runtimeConfig.public.auth, {
|
|
562
|
+
redirects: {
|
|
563
|
+
login: options.redirects?.login ?? "/login",
|
|
564
|
+
guest: options.redirects?.guest ?? "/",
|
|
565
|
+
authenticated: options.redirects?.authenticated,
|
|
566
|
+
logout: options.redirects?.logout
|
|
567
|
+
},
|
|
568
|
+
preserveRedirect: options.preserveRedirect ?? true,
|
|
569
|
+
redirectQueryKey: options.redirectQueryKey ?? "redirect",
|
|
570
|
+
useDatabase: databaseProvider !== "none",
|
|
571
|
+
databaseProvider,
|
|
572
|
+
clientOnly,
|
|
573
|
+
session: {
|
|
574
|
+
skipHydratedSsrGetSession: options.session?.skipHydratedSsrGetSession ?? false
|
|
575
|
+
}
|
|
576
|
+
});
|
|
577
|
+
if (clientOnly) {
|
|
578
|
+
const siteUrl = nuxt.options.runtimeConfig.public.siteUrl;
|
|
579
|
+
if (!siteUrl)
|
|
580
|
+
consola.warn("clientOnly mode: set runtimeConfig.public.siteUrl (or NUXT_PUBLIC_SITE_URL) to your frontend URL");
|
|
581
|
+
consola.info("clientOnly mode enabled - server utilities (serverAuth, getRequestSession, getUserSession, requireUserSession) are not available");
|
|
582
|
+
return { useHubKV, secondaryStorageEnabled };
|
|
583
|
+
}
|
|
584
|
+
const currentSecret = nuxt.options.runtimeConfig.betterAuthSecret;
|
|
585
|
+
nuxt.options.runtimeConfig.betterAuthSecret = currentSecret || process.env.NUXT_BETTER_AUTH_SECRET || process.env.BETTER_AUTH_SECRET || "";
|
|
586
|
+
const betterAuthSecret = nuxt.options.runtimeConfig.betterAuthSecret;
|
|
587
|
+
if (!nuxt.options.dev && !nuxt.options._prepare && !betterAuthSecret) {
|
|
588
|
+
throw new Error("[nuxt-better-auth] NUXT_BETTER_AUTH_SECRET is required in production. Set NUXT_BETTER_AUTH_SECRET or BETTER_AUTH_SECRET environment variable.");
|
|
589
|
+
}
|
|
590
|
+
if (betterAuthSecret && betterAuthSecret.length < 32) {
|
|
591
|
+
throw new Error("[nuxt-better-auth] NUXT_BETTER_AUTH_SECRET must be at least 32 characters for security");
|
|
592
|
+
}
|
|
593
|
+
nuxt.options.runtimeConfig.auth = defu(nuxt.options.runtimeConfig.auth, {
|
|
594
|
+
hubSecondaryStorage: options.hubSecondaryStorage ?? false
|
|
595
|
+
});
|
|
596
|
+
return { useHubKV, secondaryStorageEnabled };
|
|
597
|
+
}
|
|
598
|
+
|
|
424
599
|
function buildSecondaryStorageCode(useHubKV) {
|
|
425
600
|
if (!useHubKV)
|
|
426
601
|
return "export function createSecondaryStorage() { return undefined }";
|
|
@@ -435,6 +610,114 @@ export function createSecondaryStorage() {
|
|
|
435
610
|
}
|
|
436
611
|
function buildDatabaseCode(input) {
|
|
437
612
|
if (input.provider === "nuxthub") {
|
|
613
|
+
if (input.hubDialect === "postgresql") {
|
|
614
|
+
return `import { db } from '@nuxthub/db'
|
|
615
|
+
import * as schema from './schema.${input.hubDialect}.mjs'
|
|
616
|
+
import { drizzleAdapter } from 'better-auth/adapters/drizzle'
|
|
617
|
+
import { drizzle } from 'drizzle-orm/postgres-js'
|
|
618
|
+
import postgres from 'postgres'
|
|
619
|
+
|
|
620
|
+
const dialect = 'pg'
|
|
621
|
+
const requestDatabaseKey = Symbol.for('nuxt-better-auth.requestDatabase')
|
|
622
|
+
const fallbackRequestDatabaseContext = new WeakMap()
|
|
623
|
+
|
|
624
|
+
function getRequestDatabaseContext(event) {
|
|
625
|
+
const eventWithContext = event
|
|
626
|
+
if (eventWithContext?.context && typeof eventWithContext.context === 'object')
|
|
627
|
+
return eventWithContext.context
|
|
628
|
+
|
|
629
|
+
let context = fallbackRequestDatabaseContext.get(event)
|
|
630
|
+
if (!context) {
|
|
631
|
+
context = {}
|
|
632
|
+
fallbackRequestDatabaseContext.set(event, context)
|
|
633
|
+
}
|
|
634
|
+
return context
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
function createHyperdriveAdapter(client) {
|
|
638
|
+
return drizzleAdapter(drizzle({ client, schema }), { provider: dialect, schema, usePlural: ${input.usePlural}, camelCase: ${input.camelCase} })
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
function getCloudflareContext(event) {
|
|
642
|
+
return event?.context?.cloudflare
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
function resolveHyperdrive(event) {
|
|
646
|
+
const cloudflareEnv = getCloudflareContext(event)?.env
|
|
647
|
+
return cloudflareEnv?.POSTGRES || process.env.POSTGRES || globalThis.__env__?.POSTGRES || globalThis.POSTGRES
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
function scheduleCleanup(event, cleanup) {
|
|
651
|
+
const cloudflareContext = getCloudflareContext(event)
|
|
652
|
+
if (typeof cloudflareContext?.context?.waitUntil === 'function') {
|
|
653
|
+
cloudflareContext.context.waitUntil(cleanup)
|
|
654
|
+
return
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
if (typeof event?.context?.waitUntil === 'function') {
|
|
658
|
+
event.context.waitUntil(cleanup)
|
|
659
|
+
return
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
const waitUntil = event?.waitUntil || event?.req?.waitUntil || event?.node?.req?.waitUntil
|
|
663
|
+
if (typeof waitUntil === 'function')
|
|
664
|
+
waitUntil.call(event?.req || event?.node?.req || event, cleanup)
|
|
665
|
+
else
|
|
666
|
+
void cleanup
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
function registerClientCleanup(event, client) {
|
|
670
|
+
const response = event?.node?.res
|
|
671
|
+
if (!response || typeof response.once !== 'function')
|
|
672
|
+
return
|
|
673
|
+
|
|
674
|
+
let closed = false
|
|
675
|
+
|
|
676
|
+
const cleanup = () => {
|
|
677
|
+
if (closed)
|
|
678
|
+
return
|
|
679
|
+
|
|
680
|
+
closed = true
|
|
681
|
+
const close = client.end({ timeout: 0 }).catch(() => {})
|
|
682
|
+
scheduleCleanup(event, close)
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
response.once('finish', cleanup)
|
|
686
|
+
response.once('close', cleanup)
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
export function createDatabase(event) {
|
|
690
|
+
const hyperdrive = resolveHyperdrive(event)
|
|
691
|
+
if (!hyperdrive?.connectionString)
|
|
692
|
+
return drizzleAdapter(db, { provider: dialect, schema, usePlural: ${input.usePlural}, camelCase: ${input.camelCase} })
|
|
693
|
+
|
|
694
|
+
if (event) {
|
|
695
|
+
const context = getRequestDatabaseContext(event)
|
|
696
|
+
const cached = context[requestDatabaseKey]
|
|
697
|
+
if (cached)
|
|
698
|
+
return cached
|
|
699
|
+
|
|
700
|
+
const client = postgres(hyperdrive.connectionString, {
|
|
701
|
+
prepare: false,
|
|
702
|
+
onnotice: () => {},
|
|
703
|
+
max: 1,
|
|
704
|
+
})
|
|
705
|
+
const database = createHyperdriveAdapter(client)
|
|
706
|
+
|
|
707
|
+
context[requestDatabaseKey] = database
|
|
708
|
+
registerClientCleanup(event, client)
|
|
709
|
+
return database
|
|
710
|
+
}
|
|
711
|
+
const client = postgres(hyperdrive.connectionString, {
|
|
712
|
+
prepare: false,
|
|
713
|
+
onnotice: () => {},
|
|
714
|
+
max: 1,
|
|
715
|
+
})
|
|
716
|
+
|
|
717
|
+
return createHyperdriveAdapter(client)
|
|
718
|
+
}
|
|
719
|
+
export { db }`;
|
|
720
|
+
}
|
|
438
721
|
return `import { db } from '@nuxthub/db'
|
|
439
722
|
import * as schema from './schema.${input.hubDialect}.mjs'
|
|
440
723
|
import { drizzleAdapter } from 'better-auth/adapters/drizzle'
|
|
@@ -446,9 +729,153 @@ export { db }`;
|
|
|
446
729
|
return `export function createDatabase() { return undefined }
|
|
447
730
|
export const db = undefined`;
|
|
448
731
|
}
|
|
732
|
+
function buildSchemaExportCode(hasHubDb, hubDialect) {
|
|
733
|
+
if (!hasHubDb)
|
|
734
|
+
return "export const schema = undefined\n";
|
|
735
|
+
return `export * from './schema.${hubDialect}.mjs'
|
|
736
|
+
import * as schema from './schema.${hubDialect}.mjs'
|
|
737
|
+
export { schema }
|
|
738
|
+
`;
|
|
739
|
+
}
|
|
740
|
+
function buildAuthRouteRulesCode(authRouteRules) {
|
|
741
|
+
return `export const authRouteRules = ${JSON.stringify(authRouteRules, null, 2)}
|
|
742
|
+
`;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
function assertConfigPresence(configs, clientOnly) {
|
|
746
|
+
if (!clientOnly && !configs.server.exists)
|
|
747
|
+
throw new Error(`[nuxt-better-auth] Missing ${configs.server.file}.ts - export default defineServerAuth(...)`);
|
|
748
|
+
if (!configs.client.exists)
|
|
749
|
+
throw new Error(`[nuxt-better-auth] Missing ${configs.client.file}.ts - export default defineClientAuth(...)`);
|
|
750
|
+
}
|
|
751
|
+
function createDefaultDatabaseProviders(buildContext) {
|
|
752
|
+
return {
|
|
753
|
+
nuxthub: {
|
|
754
|
+
priority: 100,
|
|
755
|
+
isEnabled: ({ hasHubDbAvailable: enabled }) => enabled,
|
|
756
|
+
buildDatabaseCode: () => buildDatabaseCode({
|
|
757
|
+
provider: "nuxthub",
|
|
758
|
+
...buildContext
|
|
759
|
+
})
|
|
760
|
+
},
|
|
761
|
+
none: {
|
|
762
|
+
priority: 0,
|
|
763
|
+
buildDatabaseCode: () => buildDatabaseCode({
|
|
764
|
+
provider: "none",
|
|
765
|
+
...buildContext
|
|
766
|
+
})
|
|
767
|
+
}
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
function collectAuthRouteRules(nuxt) {
|
|
771
|
+
const runtimeRouteRulesSource = nuxt.options.nitro?.routeRules || nuxt.options.routeRules || {};
|
|
772
|
+
return Object.fromEntries(
|
|
773
|
+
Object.entries(runtimeRouteRulesSource).flatMap(([path, rule]) => {
|
|
774
|
+
if (!rule || typeof rule !== "object" || !("auth" in rule))
|
|
775
|
+
return [];
|
|
776
|
+
return [[path, { auth: rule.auth }]];
|
|
777
|
+
})
|
|
778
|
+
);
|
|
779
|
+
}
|
|
780
|
+
async function resolveAuthModuleSetup(input, dependencies = {}) {
|
|
781
|
+
const { nuxt, options, runtimeTypesAugmentPath, consola } = input;
|
|
782
|
+
const hasNuxtModuleFn = dependencies.hasNuxtModule ?? hasNuxtModule;
|
|
783
|
+
const clientOnly = options.clientOnly ?? false;
|
|
784
|
+
const configs = resolveAuthConfigDescriptors(nuxt, {
|
|
785
|
+
server: options.serverConfig,
|
|
786
|
+
client: options.clientConfig
|
|
787
|
+
}, {
|
|
788
|
+
configExists: dependencies.configExists
|
|
789
|
+
});
|
|
790
|
+
assertConfigPresence(configs, clientOnly);
|
|
791
|
+
const aliases = {
|
|
792
|
+
"#nuxt-better-auth": runtimeTypesAugmentPath,
|
|
793
|
+
"#auth/server": clientOnly ? void 0 : configs.server.path,
|
|
794
|
+
"#auth/client": configs.client.path
|
|
795
|
+
};
|
|
796
|
+
nuxt.options.alias["#nuxt-better-auth"] = aliases["#nuxt-better-auth"];
|
|
797
|
+
if (aliases["#auth/server"])
|
|
798
|
+
nuxt.options.alias["#auth/server"] = aliases["#auth/server"];
|
|
799
|
+
nuxt.options.alias["#auth/client"] = aliases["#auth/client"];
|
|
800
|
+
const hasNuxtHub = hasNuxtModuleFn("@nuxthub/core", nuxt);
|
|
801
|
+
const hub = hasNuxtHub ? nuxt.options.hub : void 0;
|
|
802
|
+
const hasHubDbAvailable = !clientOnly && hasNuxtHub && !!hub?.db;
|
|
803
|
+
const hubDialect = getHubDialect(hub) ?? "sqlite";
|
|
804
|
+
const usePlural = options.schema?.usePlural ?? false;
|
|
805
|
+
const camelCase = (options.schema?.casing ?? getHubCasing(hub)) !== "snake_case";
|
|
806
|
+
let providerId = "none";
|
|
807
|
+
let providerDefinition;
|
|
808
|
+
if (!clientOnly) {
|
|
809
|
+
const buildContext = { hubDialect, usePlural, camelCase };
|
|
810
|
+
const providers = createDefaultDatabaseProviders(buildContext);
|
|
811
|
+
const enabledContext = {
|
|
812
|
+
nuxt,
|
|
813
|
+
options,
|
|
814
|
+
clientOnly,
|
|
815
|
+
hasHubDbAvailable
|
|
816
|
+
};
|
|
817
|
+
await nuxt.callHook("better-auth:database:providers", providers);
|
|
818
|
+
const resolvedProvider = resolveDatabaseProvider({
|
|
819
|
+
providers,
|
|
820
|
+
context: enabledContext
|
|
821
|
+
});
|
|
822
|
+
providerId = resolvedProvider.id;
|
|
823
|
+
providerDefinition = resolvedProvider.definition;
|
|
824
|
+
}
|
|
825
|
+
const runtime = setupRuntimeConfig({
|
|
826
|
+
nuxt,
|
|
827
|
+
options,
|
|
828
|
+
clientOnly,
|
|
829
|
+
databaseProvider: providerId,
|
|
830
|
+
hasNuxtHub,
|
|
831
|
+
hub,
|
|
832
|
+
consola
|
|
833
|
+
});
|
|
834
|
+
if (runtime.useHubKV && !nuxt.options.alias["hub:kv"]) {
|
|
835
|
+
throw new Error("[nuxt-better-auth] hub:kv not found. Ensure @nuxthub/core is loaded before this module and hub.kv is enabled.");
|
|
836
|
+
}
|
|
837
|
+
const hasHubDb = providerId === "nuxthub";
|
|
838
|
+
if (hasHubDb && !nuxt.options.alias["hub:db"]) {
|
|
839
|
+
throw new Error("[nuxt-better-auth] hub:db not found. Ensure @nuxthub/core is loaded before this module and hub.db is configured.");
|
|
840
|
+
}
|
|
841
|
+
return {
|
|
842
|
+
clientOnly,
|
|
843
|
+
configs,
|
|
844
|
+
aliases,
|
|
845
|
+
hub: {
|
|
846
|
+
hasNuxtHub,
|
|
847
|
+
options: hub,
|
|
848
|
+
hasHubDbAvailable
|
|
849
|
+
},
|
|
850
|
+
database: {
|
|
851
|
+
providerId,
|
|
852
|
+
hasHubDb,
|
|
853
|
+
providerDefinition,
|
|
854
|
+
buildContext: clientOnly ? void 0 : { hubDialect, usePlural, camelCase }
|
|
855
|
+
},
|
|
856
|
+
runtime,
|
|
857
|
+
prepareTypes: clientOnly ? void 0 : {
|
|
858
|
+
serverDir: dirname(configs.server.path),
|
|
859
|
+
hasHubDb
|
|
860
|
+
},
|
|
861
|
+
serverTypes: clientOnly ? void 0 : {
|
|
862
|
+
serverConfigPath: configs.server.path,
|
|
863
|
+
hasHubDb
|
|
864
|
+
},
|
|
865
|
+
sharedTypes: {
|
|
866
|
+
clientConfigPath: configs.client.path
|
|
867
|
+
},
|
|
868
|
+
schemaGeneration: hasHubDb ? {
|
|
869
|
+
serverConfigPath: configs.server.path,
|
|
870
|
+
hubSecondaryStorage: options.hubSecondaryStorage ?? false,
|
|
871
|
+
externalizeNuxtHubDatabase: true
|
|
872
|
+
} : void 0
|
|
873
|
+
};
|
|
874
|
+
}
|
|
449
875
|
|
|
450
876
|
function registerServerTypeTemplates(input) {
|
|
451
|
-
const { serverConfigPath, hasHubDb, runtimeTypesPath } = input;
|
|
877
|
+
const { serverConfigPath, hasHubDb, runtimeTypesPath, sharedServerConfigSafe } = input;
|
|
878
|
+
const serverConfigTypeTemplateOptions = sharedServerConfigSafe ? { nuxt: true, nitro: true, node: true, shared: true } : { nuxt: true, nitro: true, node: true };
|
|
452
879
|
addTypeTemplate({
|
|
453
880
|
filename: "types/auth-secondary-storage.d.ts",
|
|
454
881
|
getContents: () => `
|
|
@@ -461,17 +888,17 @@ declare module '#auth/secondary-storage' {
|
|
|
461
888
|
export function createSecondaryStorage(): SecondaryStorage | undefined
|
|
462
889
|
}
|
|
463
890
|
`
|
|
464
|
-
}, { nitro: true
|
|
891
|
+
}, { nitro: true });
|
|
465
892
|
addTypeTemplate({
|
|
466
893
|
filename: "types/auth-database.d.ts",
|
|
467
894
|
getContents: () => `
|
|
468
895
|
declare module '#auth/database' {
|
|
469
896
|
import type { BetterAuthOptions } from 'better-auth'
|
|
470
|
-
export function createDatabase(): BetterAuthOptions['database']
|
|
897
|
+
export function createDatabase(event?: import('h3').H3Event): BetterAuthOptions['database']
|
|
471
898
|
export const db: ${hasHubDb ? `typeof import('@nuxthub/db')['db']` : "undefined"}
|
|
472
899
|
}
|
|
473
900
|
`
|
|
474
|
-
}, { nitro: true
|
|
901
|
+
}, { nitro: true });
|
|
475
902
|
addTypeTemplate({
|
|
476
903
|
filename: "types/auth-schema.d.ts",
|
|
477
904
|
getContents: () => `
|
|
@@ -489,13 +916,39 @@ declare module '#auth/schema' {
|
|
|
489
916
|
} | undefined
|
|
490
917
|
}
|
|
491
918
|
`
|
|
492
|
-
}, { nitro: true
|
|
919
|
+
}, { nitro: true });
|
|
920
|
+
addTypeTemplate({
|
|
921
|
+
filename: "types/nuxt-better-auth-server-context.d.ts",
|
|
922
|
+
getContents: () => `
|
|
923
|
+
/// <reference path="./nitro-imports.d.ts" />
|
|
924
|
+
/// <reference path="./auth-database.d.ts" />
|
|
925
|
+
/// <reference path="./auth-schema.d.ts" />
|
|
926
|
+
/// <reference path="./auth-secondary-storage.d.ts" />
|
|
927
|
+
${hasHubDb ? '/// <reference path="../hub/db.d.ts" />' : ""}
|
|
928
|
+
|
|
929
|
+
export {}
|
|
930
|
+
`
|
|
931
|
+
}, { node: true });
|
|
932
|
+
addTypeTemplate({
|
|
933
|
+
filename: "types/nuxt-better-auth-config-context.d.ts",
|
|
934
|
+
getContents: () => `
|
|
935
|
+
import type { RuntimeConfig } from 'nuxt/schema'
|
|
936
|
+
|
|
937
|
+
declare module '@onmax/nuxt-better-auth/config' {
|
|
938
|
+
interface ServerAuthContextExtension {
|
|
939
|
+
runtimeConfig: RuntimeConfig
|
|
940
|
+
db: ${hasHubDb ? `typeof import('@nuxthub/db')['db']` : "undefined"}
|
|
941
|
+
requestOrigin?: string
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
`
|
|
946
|
+
}, { nuxt: true, nitro: true, node: true, shared: true });
|
|
493
947
|
addTypeTemplate({
|
|
494
948
|
filename: "types/nuxt-better-auth-infer.d.ts",
|
|
495
949
|
getContents: () => `
|
|
496
950
|
import type { BetterAuthOptions, BetterAuthPlugin, InferPluginTypes, UnionToIntersection } from 'better-auth'
|
|
497
951
|
import type { InferFieldsOutput } from 'better-auth/db'
|
|
498
|
-
import type { RuntimeConfig } from 'nuxt/schema'
|
|
499
952
|
import type createServerAuth from '${serverConfigPath}'
|
|
500
953
|
|
|
501
954
|
type _RawConfig = ReturnType<typeof createServerAuth>
|
|
@@ -525,28 +978,10 @@ type _SessionFallback = _InferModelFieldsFromPlugins<_RawPlugins, 'session'> & _
|
|
|
525
978
|
declare module '#nuxt-better-auth' {
|
|
526
979
|
interface AuthUser extends _UserFallback {}
|
|
527
980
|
interface AuthSession extends _SessionFallback {}
|
|
528
|
-
interface ServerAuthContext {
|
|
529
|
-
runtimeConfig: RuntimeConfig
|
|
530
|
-
db: ${hasHubDb ? `typeof import('@nuxthub/db')['db']` : "undefined"}
|
|
531
|
-
}
|
|
532
981
|
type PluginTypes = InferPluginTypes<_Config>
|
|
533
982
|
}
|
|
534
|
-
|
|
535
|
-
interface _AugmentedServerAuthContext {
|
|
536
|
-
runtimeConfig: RuntimeConfig
|
|
537
|
-
db: ${hasHubDb ? `typeof import('@nuxthub/db')['db']` : "undefined"}
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
declare module '@onmax/nuxt-better-auth/config' {
|
|
541
|
-
import type { BetterAuthOptions, BetterAuthPlugin } from 'better-auth'
|
|
542
|
-
type ServerAuthConfig = Omit<BetterAuthOptions, 'secret' | 'baseURL'> & {
|
|
543
|
-
plugins?: readonly BetterAuthPlugin[]
|
|
544
|
-
}
|
|
545
|
-
export function defineServerAuth<const R>(config: (ctx: _AugmentedServerAuthContext) => R & ServerAuthConfig): (ctx: _AugmentedServerAuthContext) => R
|
|
546
|
-
export function defineServerAuth<const R>(config: R & ServerAuthConfig): (ctx: _AugmentedServerAuthContext) => R
|
|
547
|
-
}
|
|
548
983
|
`
|
|
549
|
-
},
|
|
984
|
+
}, serverConfigTypeTemplateOptions);
|
|
550
985
|
addTypeTemplate({
|
|
551
986
|
filename: "types/nuxt-better-auth-social-providers.d.ts",
|
|
552
987
|
getContents: () => `
|
|
@@ -562,7 +997,7 @@ declare module '#nuxt-better-auth' {
|
|
|
562
997
|
}
|
|
563
998
|
}
|
|
564
999
|
`
|
|
565
|
-
},
|
|
1000
|
+
}, serverConfigTypeTemplateOptions);
|
|
566
1001
|
addTypeTemplate({
|
|
567
1002
|
filename: "types/nuxt-better-auth-nitro.d.ts",
|
|
568
1003
|
getContents: () => `
|
|
@@ -669,6 +1104,7 @@ declare module 'nuxt/dist/app/composables/fetch' {
|
|
|
669
1104
|
PickKeys extends import('nuxt/dist/app/composables/asyncData').KeysOf<DataT> = import('nuxt/dist/app/composables/asyncData').KeysOf<DataT>,
|
|
670
1105
|
DefaultT = DataT,
|
|
671
1106
|
>(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>
|
|
1107
|
+
export function useFetch(request: string | import('vue').Ref<string> | (() => string), opts?: any): any
|
|
672
1108
|
|
|
673
1109
|
export function useLazyFetch<
|
|
674
1110
|
ErrorT = FetchError,
|
|
@@ -688,6 +1124,7 @@ declare module 'nuxt/dist/app/composables/fetch' {
|
|
|
688
1124
|
PickKeys extends import('nuxt/dist/app/composables/asyncData').KeysOf<DataT> = import('nuxt/dist/app/composables/asyncData').KeysOf<DataT>,
|
|
689
1125
|
DefaultT = DataT,
|
|
690
1126
|
>(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>
|
|
1127
|
+
export function useLazyFetch(request: string | import('vue').Ref<string> | (() => string), opts?: any): any
|
|
691
1128
|
}
|
|
692
1129
|
|
|
693
1130
|
declare module 'nuxt/app' {
|
|
@@ -709,6 +1146,7 @@ declare module 'nuxt/app' {
|
|
|
709
1146
|
PickKeys extends import('nuxt/dist/app/composables/asyncData').KeysOf<DataT> = import('nuxt/dist/app/composables/asyncData').KeysOf<DataT>,
|
|
710
1147
|
DefaultT = DataT,
|
|
711
1148
|
>(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>
|
|
1149
|
+
export function useFetch(request: string | import('vue').Ref<string> | (() => string), opts?: any): any
|
|
712
1150
|
|
|
713
1151
|
export function useLazyFetch<
|
|
714
1152
|
ErrorT = FetchError,
|
|
@@ -728,6 +1166,7 @@ declare module 'nuxt/app' {
|
|
|
728
1166
|
PickKeys extends import('nuxt/dist/app/composables/asyncData').KeysOf<DataT> = import('nuxt/dist/app/composables/asyncData').KeysOf<DataT>,
|
|
729
1167
|
DefaultT = DataT,
|
|
730
1168
|
>(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>
|
|
1169
|
+
export function useLazyFetch(request: string | import('vue').Ref<string> | (() => string), opts?: any): any
|
|
731
1170
|
}
|
|
732
1171
|
|
|
733
1172
|
declare module 'nitropack' {
|
|
@@ -748,9 +1187,18 @@ declare module 'nitropack/types' {
|
|
|
748
1187
|
}
|
|
749
1188
|
interface InternalApi extends _GeneratedAuthInternalApi {}
|
|
750
1189
|
}
|
|
1190
|
+
declare module 'nitro/types' {
|
|
1191
|
+
interface NitroRouteRules {
|
|
1192
|
+
auth?: import('${runtimeTypesPath}').AuthMeta
|
|
1193
|
+
}
|
|
1194
|
+
interface NitroRouteConfig {
|
|
1195
|
+
auth?: import('${runtimeTypesPath}').AuthMeta
|
|
1196
|
+
}
|
|
1197
|
+
interface InternalApi extends _GeneratedAuthInternalApi {}
|
|
1198
|
+
}
|
|
751
1199
|
export {}
|
|
752
1200
|
`
|
|
753
|
-
}, {
|
|
1201
|
+
}, { nitro: true, node: true });
|
|
754
1202
|
}
|
|
755
1203
|
function registerSharedTypeTemplates(input) {
|
|
756
1204
|
addTypeTemplate({
|
|
@@ -778,15 +1226,30 @@ declare module '#nuxt-better-auth' {
|
|
|
778
1226
|
}
|
|
779
1227
|
|
|
780
1228
|
const consola = consola$1.withTag("nuxt-better-auth");
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
1229
|
+
const serverAliasImportRE = /from\s+['"]#server/;
|
|
1230
|
+
const layersAliasImportRE = /from\s+['"]#layers\//;
|
|
1231
|
+
const rootAliasImportRE = /from\s+['"]~~/;
|
|
1232
|
+
const workspaceAliasImportRE = /from\s+['"]@@/;
|
|
1233
|
+
const dbIdentifierRE = /\bdb\b/;
|
|
1234
|
+
const sessionHookAfterIdentifierRE = /\bsessionHookAfter\b/;
|
|
1235
|
+
const nuxtHubDbImportRE = /@nuxthub\/db/;
|
|
1236
|
+
function isServerConfigSharedTypeSafe(serverConfigPath) {
|
|
1237
|
+
const resolvedPath = [
|
|
1238
|
+
serverConfigPath,
|
|
1239
|
+
`${serverConfigPath}.ts`,
|
|
1240
|
+
`${serverConfigPath}.mts`,
|
|
1241
|
+
`${serverConfigPath}.cts`,
|
|
1242
|
+
`${serverConfigPath}.js`,
|
|
1243
|
+
`${serverConfigPath}.mjs`,
|
|
1244
|
+
`${serverConfigPath}.cjs`
|
|
1245
|
+
].find((path) => existsSync(path));
|
|
1246
|
+
if (!resolvedPath)
|
|
1247
|
+
return false;
|
|
1248
|
+
const contents = readFileSync(resolvedPath, "utf8");
|
|
1249
|
+
return !(serverAliasImportRE.test(contents) || layersAliasImportRE.test(contents) || rootAliasImportRE.test(contents) || workspaceAliasImportRE.test(contents) || dbIdentifierRE.test(contents) || sessionHookAfterIdentifierRE.test(contents) || nuxtHubDbImportRE.test(contents));
|
|
786
1250
|
}
|
|
787
|
-
async function createDefaultAuthConfigFiles(
|
|
788
|
-
const
|
|
789
|
-
const clientPath = join(srcDir, "auth.config.ts");
|
|
1251
|
+
async function createDefaultAuthConfigFiles(nuxt) {
|
|
1252
|
+
const configs = resolveAuthConfigDescriptors(nuxt);
|
|
790
1253
|
const serverTemplate = `import { defineServerAuth } from '@onmax/nuxt-better-auth/config'
|
|
791
1254
|
|
|
792
1255
|
export default defineServerAuth({
|
|
@@ -797,16 +1260,17 @@ export default defineServerAuth({
|
|
|
797
1260
|
|
|
798
1261
|
export default defineClientAuth({})
|
|
799
1262
|
`;
|
|
800
|
-
if (
|
|
1263
|
+
if (configs.server.shouldCreateDefaultFile) {
|
|
1264
|
+
const serverPath = `${configs.server.path}.ts`;
|
|
801
1265
|
await mkdir(dirname(serverPath), { recursive: true });
|
|
802
1266
|
await writeFile(serverPath, serverTemplate);
|
|
803
|
-
consola.success(
|
|
1267
|
+
consola.success(`Created ${relative(configs.server.declaringLayerRoot, serverPath)}`);
|
|
804
1268
|
}
|
|
805
|
-
if (
|
|
1269
|
+
if (configs.client.shouldCreateDefaultFile) {
|
|
1270
|
+
const clientPath = `${configs.client.path}.ts`;
|
|
806
1271
|
await mkdir(dirname(clientPath), { recursive: true });
|
|
807
1272
|
await writeFile(clientPath, clientTemplate);
|
|
808
|
-
|
|
809
|
-
consola.success(`Created ${relativePath}`);
|
|
1273
|
+
consola.success(`Created ${relative(configs.client.declaringLayerRoot, clientPath)}`);
|
|
810
1274
|
}
|
|
811
1275
|
}
|
|
812
1276
|
const module$1 = defineNuxtModule({
|
|
@@ -824,153 +1288,90 @@ const module$1 = defineNuxtModule({
|
|
|
824
1288
|
const configuredSecret = nuxt.options.runtimeConfig?.betterAuthSecret;
|
|
825
1289
|
const generatedSecret = await promptForSecret(nuxt.options.rootDir, consola, { configuredSecret, prepare: Boolean(nuxt.options._prepare) });
|
|
826
1290
|
if (generatedSecret)
|
|
827
|
-
process.env.
|
|
828
|
-
await createDefaultAuthConfigFiles(nuxt
|
|
1291
|
+
process.env.NUXT_BETTER_AUTH_SECRET = generatedSecret;
|
|
1292
|
+
await createDefaultAuthConfigFiles(nuxt);
|
|
829
1293
|
},
|
|
830
1294
|
async setup(options, nuxt) {
|
|
831
1295
|
const resolver = createResolver(import.meta.url);
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
if (!
|
|
843
|
-
throw new Error(`[nuxt-better-auth] Missing ${clientConfigFile}.ts - export default defineClientAuth(...)`);
|
|
844
|
-
const hasNuxtHub = hasNuxtModule("@nuxthub/core", nuxt);
|
|
845
|
-
const hub = hasNuxtHub ? nuxt.options.hub : void 0;
|
|
846
|
-
const hasHubDbAvailable = !clientOnly && hasNuxtHub && !!hub?.db;
|
|
847
|
-
const deprecatedProvider = options.database?.provider;
|
|
848
|
-
if (deprecatedProvider) {
|
|
849
|
-
throw new Error(
|
|
850
|
-
`[nuxt-better-auth] auth.database.provider has been removed. Remove auth.database.provider="${deprecatedProvider}". To configure a database, either set "database" directly in server/auth.config.ts (defineServerAuth) or install a provider module that registers better-auth:database:providers.`
|
|
851
|
-
);
|
|
852
|
-
}
|
|
853
|
-
let databaseProvider = "none";
|
|
854
|
-
let hasHubDb = false;
|
|
855
|
-
nuxt.options.alias["#nuxt-better-auth"] = resolver.resolve("./runtime/types/augment");
|
|
856
|
-
if (!clientOnly)
|
|
857
|
-
nuxt.options.alias["#auth/server"] = serverConfigPath;
|
|
858
|
-
nuxt.options.alias["#auth/client"] = clientConfigPath;
|
|
859
|
-
if (clientOnly) {
|
|
860
|
-
setupRuntimeConfig({
|
|
861
|
-
nuxt,
|
|
862
|
-
options,
|
|
863
|
-
clientOnly,
|
|
864
|
-
databaseProvider,
|
|
865
|
-
hasNuxtHub,
|
|
866
|
-
hub,
|
|
867
|
-
consola
|
|
868
|
-
});
|
|
869
|
-
} else {
|
|
870
|
-
const hubDialect = getHubDialect(hub) ?? "sqlite";
|
|
871
|
-
const usePlural = options.schema?.usePlural ?? false;
|
|
872
|
-
const camelCase = (options.schema?.casing ?? getHubCasing(hub)) !== "snake_case";
|
|
873
|
-
const providers = {
|
|
874
|
-
nuxthub: {
|
|
875
|
-
priority: 100,
|
|
876
|
-
isEnabled: ({ hasHubDbAvailable: hasHubDbAvailable2 }) => hasHubDbAvailable2,
|
|
877
|
-
buildDatabaseCode: () => buildDatabaseCode({
|
|
878
|
-
provider: "nuxthub",
|
|
879
|
-
hubDialect,
|
|
880
|
-
usePlural,
|
|
881
|
-
camelCase
|
|
882
|
-
})
|
|
883
|
-
},
|
|
884
|
-
none: {
|
|
885
|
-
priority: 0,
|
|
886
|
-
buildDatabaseCode: () => buildDatabaseCode({
|
|
887
|
-
provider: "none",
|
|
888
|
-
hubDialect,
|
|
889
|
-
usePlural,
|
|
890
|
-
camelCase
|
|
891
|
-
})
|
|
892
|
-
}
|
|
893
|
-
};
|
|
894
|
-
const enabledCtx = { nuxt, options, clientOnly, hasHubDbAvailable };
|
|
895
|
-
await nuxt.callHook("better-auth:database:providers", providers);
|
|
896
|
-
const resolvedProvider = resolveDatabaseProvider({ providers, context: enabledCtx });
|
|
897
|
-
databaseProvider = resolvedProvider.id;
|
|
898
|
-
hasHubDb = databaseProvider === "nuxthub";
|
|
899
|
-
const { useHubKV } = setupRuntimeConfig({
|
|
900
|
-
nuxt,
|
|
901
|
-
options,
|
|
902
|
-
clientOnly,
|
|
903
|
-
databaseProvider,
|
|
904
|
-
hasNuxtHub,
|
|
905
|
-
hub,
|
|
906
|
-
consola
|
|
907
|
-
});
|
|
908
|
-
if (useHubKV && !nuxt.options.alias["hub:kv"]) {
|
|
909
|
-
throw new Error("[nuxt-better-auth] hub:kv not found. Ensure @nuxthub/core is loaded before this module and hub.kv is enabled.");
|
|
910
|
-
}
|
|
1296
|
+
const setup = await resolveAuthModuleSetup({
|
|
1297
|
+
nuxt,
|
|
1298
|
+
options,
|
|
1299
|
+
runtimeTypesAugmentPath: resolver.resolve("./runtime/types/augment"),
|
|
1300
|
+
consola
|
|
1301
|
+
});
|
|
1302
|
+
nuxt.options.alias["#nuxt-better-auth"] = setup.aliases["#nuxt-better-auth"];
|
|
1303
|
+
if (setup.aliases["#auth/server"])
|
|
1304
|
+
nuxt.options.alias["#auth/server"] = setup.aliases["#auth/server"];
|
|
1305
|
+
nuxt.options.alias["#auth/client"] = setup.aliases["#auth/client"];
|
|
1306
|
+
if (!setup.clientOnly) {
|
|
911
1307
|
const secondaryStorageTemplate = addTemplate({
|
|
912
1308
|
filename: "better-auth/secondary-storage.mjs",
|
|
913
|
-
getContents: () => buildSecondaryStorageCode(useHubKV),
|
|
1309
|
+
getContents: () => buildSecondaryStorageCode(setup.runtime.useHubKV),
|
|
914
1310
|
write: true
|
|
915
1311
|
});
|
|
916
1312
|
nuxt.options.alias["#auth/secondary-storage"] = secondaryStorageTemplate.dst;
|
|
917
|
-
if (hasHubDb && !nuxt.options.alias["hub:db"]) {
|
|
918
|
-
throw new Error("[nuxt-better-auth] hub:db not found. Ensure @nuxthub/core is loaded before this module and hub.db is configured.");
|
|
919
|
-
}
|
|
920
|
-
const setupCtx = { nuxt, options, clientOnly };
|
|
921
|
-
await resolvedProvider.definition.setup?.(setupCtx);
|
|
922
|
-
const buildCtx = { hubDialect, usePlural, camelCase };
|
|
923
1313
|
const databaseTemplate = addTemplate({
|
|
924
1314
|
filename: "better-auth/database.mjs",
|
|
925
|
-
getContents: () =>
|
|
1315
|
+
getContents: () => setup.database.providerDefinition.buildDatabaseCode(setup.database.buildContext),
|
|
926
1316
|
write: true
|
|
927
1317
|
});
|
|
928
1318
|
nuxt.options.alias["#auth/database"] = databaseTemplate.dst;
|
|
929
1319
|
const schemaTemplate = addTemplate({
|
|
930
1320
|
filename: "better-auth/schema.mjs",
|
|
931
|
-
getContents: () =>
|
|
932
|
-
if (!hasHubDb)
|
|
933
|
-
return "export const schema = undefined\n";
|
|
934
|
-
return `export * from './schema.${hubDialect}.mjs'
|
|
935
|
-
import * as schema from './schema.${hubDialect}.mjs'
|
|
936
|
-
export { schema }
|
|
937
|
-
`;
|
|
938
|
-
},
|
|
1321
|
+
getContents: () => buildSchemaExportCode(setup.database.hasHubDb, setup.database.buildContext?.hubDialect ?? "sqlite"),
|
|
939
1322
|
write: true
|
|
940
1323
|
});
|
|
941
1324
|
nuxt.options.alias["#auth/schema"] = schemaTemplate.dst;
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
1325
|
+
}
|
|
1326
|
+
if (setup.prepareTypes) {
|
|
1327
|
+
registerPrepareTypesHook({
|
|
1328
|
+
nuxt,
|
|
1329
|
+
serverDir: setup.prepareTypes.serverDir,
|
|
1330
|
+
hasHubDb: setup.prepareTypes.hasHubDb
|
|
946
1331
|
});
|
|
947
|
-
if (hasHubDb)
|
|
948
|
-
await setupBetterAuthSchema(nuxt, serverConfigPath, options, consola, options.hubSecondaryStorage ?? false);
|
|
949
1332
|
}
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
if (!rule || typeof rule !== "object" || !("auth" in rule))
|
|
959
|
-
return [];
|
|
960
|
-
return [[path, { auth: rule.auth }]];
|
|
961
|
-
})
|
|
962
|
-
);
|
|
1333
|
+
if (setup.database.providerDefinition) {
|
|
1334
|
+
const setupCtx = {
|
|
1335
|
+
nuxt,
|
|
1336
|
+
options,
|
|
1337
|
+
clientOnly: setup.clientOnly
|
|
1338
|
+
};
|
|
1339
|
+
await setup.database.providerDefinition.setup?.(setupCtx);
|
|
1340
|
+
}
|
|
963
1341
|
const authRouteRulesTemplate = addTemplate({
|
|
964
1342
|
filename: "better-auth/route-rules.mjs",
|
|
965
|
-
getContents: () =>
|
|
966
|
-
`,
|
|
1343
|
+
getContents: () => buildAuthRouteRulesCode(collectAuthRouteRules(nuxt)),
|
|
967
1344
|
write: true
|
|
968
1345
|
});
|
|
969
1346
|
nuxt.options.alias["#auth/route-rules"] = authRouteRulesTemplate.dst;
|
|
1347
|
+
if (setup.serverTypes) {
|
|
1348
|
+
registerServerTypeTemplates({
|
|
1349
|
+
serverConfigPath: setup.serverTypes.serverConfigPath,
|
|
1350
|
+
hasHubDb: setup.serverTypes.hasHubDb,
|
|
1351
|
+
runtimeTypesPath: resolver.resolve("./runtime/types"),
|
|
1352
|
+
sharedServerConfigSafe: isServerConfigSharedTypeSafe(setup.serverTypes.serverConfigPath)
|
|
1353
|
+
});
|
|
1354
|
+
}
|
|
1355
|
+
if (setup.schemaGeneration) {
|
|
1356
|
+
if (setup.schemaGeneration.externalizeNuxtHubDatabase)
|
|
1357
|
+
registerNuxtHubDatabaseExternalHook(nuxt);
|
|
1358
|
+
await setupBetterAuthSchema(
|
|
1359
|
+
nuxt,
|
|
1360
|
+
setup.schemaGeneration.serverConfigPath,
|
|
1361
|
+
options,
|
|
1362
|
+
consola,
|
|
1363
|
+
setup.schemaGeneration.hubSecondaryStorage
|
|
1364
|
+
);
|
|
1365
|
+
}
|
|
1366
|
+
registerSharedTypeTemplates({
|
|
1367
|
+
runtimeTypesAugmentPath: setup.aliases["#nuxt-better-auth"],
|
|
1368
|
+
runtimeTypesPath: resolver.resolve("./runtime/types"),
|
|
1369
|
+
clientConfigPath: setup.sharedTypes.clientConfigPath
|
|
1370
|
+
});
|
|
970
1371
|
registerTemplateHmrHook(nuxt);
|
|
971
|
-
registerServerRuntime({ clientOnly, resolve: resolver.resolve });
|
|
1372
|
+
registerServerRuntime({ clientOnly: setup.clientOnly, resolve: resolver.resolve });
|
|
972
1373
|
registerAuthMiddlewareHook(nuxt, resolver.resolve);
|
|
973
|
-
await registerDevtools({ nuxt, clientOnly, hasHubDb, resolve: resolver.resolve });
|
|
1374
|
+
await registerDevtools({ nuxt, clientOnly: setup.clientOnly, hasHubDb: setup.database.hasHubDb, resolve: resolver.resolve });
|
|
974
1375
|
registerRouteRulesMetaHook(nuxt);
|
|
975
1376
|
}
|
|
976
1377
|
});
|