@nuxtjs/better-auth 0.2.1 → 0.2.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.
- package/dist/module.d.mts +14 -5
- package/dist/module.json +1 -1
- package/dist/module.mjs +198 -131
- package/dist/runtime/app/composables/useUserSession.js +15 -9
- package/dist/runtime/config.d.ts +29 -5
- package/dist/runtime/config.js +22 -4
- package/dist/runtime/server/api/_better-auth/config.get.js +1 -1
- package/dist/runtime/server/utils/auth.d.ts +1 -0
- package/dist/runtime/server/utils/auth.js +13 -2
- package/package.json +1 -1
package/dist/module.d.mts
CHANGED
|
@@ -2,11 +2,15 @@ import * as _nuxt_schema from '@nuxt/schema';
|
|
|
2
2
|
import { Nuxt } from '@nuxt/schema';
|
|
3
3
|
import { BetterAuthModuleOptions } from '../dist/runtime/config.js';
|
|
4
4
|
export { BetterAuthModuleOptions, defineClientAuth, defineServerAuth } from '../dist/runtime/config.js';
|
|
5
|
-
import {
|
|
5
|
+
import { BetterAuthPlugin } from 'better-auth';
|
|
6
6
|
export { AppSession, Auth, AuthActionError, AuthMeta, AuthMode, AuthRouteRules, AuthSession, AuthSocialProviderId, AuthUser, InferSession, InferUser, RequireSessionOptions, ServerAuthContext, UserMatch } from '../dist/runtime/types.js';
|
|
7
7
|
|
|
8
8
|
type DbDialect = 'sqlite' | 'postgresql' | 'mysql';
|
|
9
9
|
|
|
10
|
+
interface BetterAuthPluginSources {
|
|
11
|
+
server?: string[];
|
|
12
|
+
client?: string[];
|
|
13
|
+
}
|
|
10
14
|
interface BetterAuthDatabaseProviderBuildContext {
|
|
11
15
|
hubDialect: DbDialect;
|
|
12
16
|
usePlural: boolean;
|
|
@@ -28,12 +32,17 @@ interface BetterAuthDatabaseProviderDefinition {
|
|
|
28
32
|
}
|
|
29
33
|
declare module '@nuxt/schema' {
|
|
30
34
|
interface NuxtHooks {
|
|
35
|
+
/** Register absolute plugin module paths during module setup. Sources are additive and are not deduplicated. */
|
|
36
|
+
'better-auth:plugins:extend': (sources: BetterAuthPluginSources) => void | Promise<void>;
|
|
31
37
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* @param config -
|
|
38
|
+
* Add plugin schemas to generated Better Auth database tables.
|
|
39
|
+
* This build-time hook does not install plugins in the runtime auth instance.
|
|
40
|
+
* @param config - Plugins to include during schema generation
|
|
41
|
+
* @param config.plugins - Better Auth plugins whose schemas should be generated
|
|
35
42
|
*/
|
|
36
|
-
'better-auth:config:extend': (config:
|
|
43
|
+
'better-auth:config:extend': (config: {
|
|
44
|
+
plugins?: BetterAuthPlugin[];
|
|
45
|
+
}) => void | Promise<void>;
|
|
37
46
|
/**
|
|
38
47
|
* Register or override Better Auth database providers.
|
|
39
48
|
* Providers are auto-selected via `isEnabled` + `priority`.
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { existsSync, statSync, writeFileSync, readFileSync } from 'node:fs';
|
|
|
2
2
|
import { mkdir, writeFile } from 'node:fs/promises';
|
|
3
3
|
import { getLayerDirectories, updateTemplates, addServerImportsDir, addServerImports, addServerScanDir, addServerHandler, addImportsDir, addPlugin, addComponentsDir, extendPages, addTemplate, hasNuxtModule, addTypeTemplate, defineNuxtModule, createResolver } from '@nuxt/kit';
|
|
4
4
|
import { consola as consola$1 } from 'consola';
|
|
5
|
-
import { isAbsolute, join, relative, dirname } from 'pathe';
|
|
5
|
+
import { isAbsolute, resolve, 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 'auth/api';
|
|
@@ -10,10 +10,10 @@ 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.2.
|
|
13
|
+
const version = "0.2.3";
|
|
14
14
|
|
|
15
15
|
const CONFIG_EXTENSIONS = [".ts", ".js"];
|
|
16
|
-
const CONFIG_EXTENSION_RE = /\.(?:ts|js)$/;
|
|
16
|
+
const CONFIG_EXTENSION_RE$1 = /\.(?:ts|js)$/;
|
|
17
17
|
const DEFAULT_CONFIG_FILES = {
|
|
18
18
|
server: "server/auth.config",
|
|
19
19
|
client: "app/auth.config"
|
|
@@ -22,8 +22,12 @@ const OPTION_KEY_BY_KIND = {
|
|
|
22
22
|
server: "serverConfig",
|
|
23
23
|
client: "clientConfig"
|
|
24
24
|
};
|
|
25
|
+
const PLUGIN_OPTION_KEY_BY_KIND = {
|
|
26
|
+
server: "serverPluginSources",
|
|
27
|
+
client: "clientPluginSources"
|
|
28
|
+
};
|
|
25
29
|
function stripConfigExtension(path) {
|
|
26
|
-
return path.replace(CONFIG_EXTENSION_RE, "");
|
|
30
|
+
return path.replace(CONFIG_EXTENSION_RE$1, "");
|
|
27
31
|
}
|
|
28
32
|
function defaultConfigExists(path) {
|
|
29
33
|
return CONFIG_EXTENSIONS.some((ext) => existsSync(`${path}${ext}`));
|
|
@@ -125,6 +129,18 @@ function resolveAuthConfigDescriptors(nuxt, files = {}, dependencies = {}) {
|
|
|
125
129
|
client: resolveAuthConfigDescriptor(nuxt, "client", files.client, dependencies)
|
|
126
130
|
};
|
|
127
131
|
}
|
|
132
|
+
function resolveAuthPluginSources(nuxt) {
|
|
133
|
+
const resolved = { server: [], client: [] };
|
|
134
|
+
for (const { directory, layer } of getLayerDirectoriesWithConfigs(nuxt)) {
|
|
135
|
+
for (const kind of ["server", "client"]) {
|
|
136
|
+
const sources = layer?.config?.auth?.[PLUGIN_OPTION_KEY_BY_KIND[kind]];
|
|
137
|
+
if (!Array.isArray(sources))
|
|
138
|
+
continue;
|
|
139
|
+
resolved[kind].push(...sources.map((source) => isAbsolute(source) ? source : resolve(directory.root, source)));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return resolved;
|
|
143
|
+
}
|
|
128
144
|
|
|
129
145
|
function resolveNitroCompatibilityImports(nuxtVersion) {
|
|
130
146
|
const major = Number.parseInt(nuxtVersion, 10);
|
|
@@ -311,6 +327,8 @@ function loadLocalEnv(rootDir) {
|
|
|
311
327
|
return;
|
|
312
328
|
process.loadEnvFile(envPath);
|
|
313
329
|
}
|
|
330
|
+
const NO_DEFAULT_EXPORT_MESSAGE = "[@nuxtjs/better-auth] auth.config.ts does not export default. Expected: export default defineServerAuth(...)";
|
|
331
|
+
const SCHEMA_NOT_REGENERATED_MESSAGE = "The schema was not regenerated and any existing generated schema file was left unchanged.";
|
|
314
332
|
async function loadUserAuthConfig(configPath, throwOnError = false, alias, runtimeConfig = {}, rootDir) {
|
|
315
333
|
const { createJiti } = await import('jiti');
|
|
316
334
|
const { defineServerAuth: runtimeDefineServerAuth } = await import('../dist/runtime/config.js');
|
|
@@ -331,17 +349,18 @@ async function loadUserAuthConfig(configPath, throwOnError = false, alias, runti
|
|
|
331
349
|
if (typeof configFn === "function") {
|
|
332
350
|
return configFn({ runtimeConfig, db: null });
|
|
333
351
|
}
|
|
334
|
-
consola$1.warn("[@nuxtjs/better-auth] auth.config.ts does not export default. Expected: export default defineServerAuth(...)");
|
|
335
352
|
if (throwOnError) {
|
|
353
|
+
consola$1.warn(NO_DEFAULT_EXPORT_MESSAGE);
|
|
336
354
|
throw new Error("auth.config.ts must export default defineServerAuth(...)");
|
|
337
355
|
}
|
|
338
|
-
|
|
356
|
+
consola$1.error(`${NO_DEFAULT_EXPORT_MESSAGE}. ${SCHEMA_NOT_REGENERATED_MESSAGE}`);
|
|
357
|
+
return null;
|
|
339
358
|
} catch (error) {
|
|
340
359
|
if (throwOnError) {
|
|
341
360
|
throw new Error(`Failed to load auth config: ${error instanceof Error ? error.message : error}`);
|
|
342
361
|
}
|
|
343
|
-
consola$1.error(
|
|
344
|
-
return
|
|
362
|
+
consola$1.error(`[@nuxtjs/better-auth] Failed to load auth config for schema generation. ${SCHEMA_NOT_REGENERATED_MESSAGE}`, error);
|
|
363
|
+
return null;
|
|
345
364
|
} finally {
|
|
346
365
|
const sharedDefineServerAuth = schemaGlobals.__nuxtBetterAuthDefineServerAuth;
|
|
347
366
|
if (sharedDefineServerAuth) {
|
|
@@ -372,6 +391,7 @@ function getHubCasing(hub) {
|
|
|
372
391
|
}
|
|
373
392
|
|
|
374
393
|
const NODE_MODULES_SEGMENT_RE = /[\\/]/;
|
|
394
|
+
const CONFIG_EXTENSION_RE = /\.[cm]?[jt]s$/;
|
|
375
395
|
function resolveSchemaSecondaryStorageInjection(hubSecondaryStorage, userHasSecondaryStorage, isProduction) {
|
|
376
396
|
if (hubSecondaryStorage === true)
|
|
377
397
|
return { inject: false };
|
|
@@ -401,11 +421,13 @@ function resolveHubSchemaPath(buildDir, rootDir, dialect, exists = existsSync) {
|
|
|
401
421
|
}
|
|
402
422
|
async function loadAuthOptions(context) {
|
|
403
423
|
const isProduction = !context.nuxt.options.dev;
|
|
404
|
-
const configFile = `${context.serverConfigPath}.ts`;
|
|
424
|
+
const configFile = CONFIG_EXTENSION_RE.test(context.serverConfigPath) ? context.serverConfigPath : `${context.serverConfigPath}.ts`;
|
|
405
425
|
const alias = Object.fromEntries(
|
|
406
426
|
Object.entries(context.nuxt.options.alias).filter(([, value]) => typeof value === "string").map(([key, value]) => [key, value])
|
|
407
427
|
);
|
|
408
428
|
const userConfig = await loadUserAuthConfig(configFile, isProduction, alias, context.nuxt.options.runtimeConfig, context.nuxt.options.rootDir);
|
|
429
|
+
if (!userConfig)
|
|
430
|
+
return null;
|
|
409
431
|
const extendedConfig = {};
|
|
410
432
|
await context.nuxt.callHook("better-auth:config:extend", extendedConfig);
|
|
411
433
|
const plugins = [...userConfig.plugins || [], ...extendedConfig.plugins || []];
|
|
@@ -419,8 +441,17 @@ async function setupBetterAuthSchema(nuxt, serverConfigPath, options, consola, h
|
|
|
419
441
|
return;
|
|
420
442
|
}
|
|
421
443
|
const context = { nuxt, serverConfigPath };
|
|
444
|
+
const nuxtWithHubHooks = nuxt;
|
|
445
|
+
nuxtWithHubHooks.hook("hub:db:schema:extend", ({ paths, dialect: hookDialect }) => {
|
|
446
|
+
const schemaPath = resolveHubSchemaPath(nuxt.options.buildDir, nuxt.options.rootDir, hookDialect);
|
|
447
|
+
if (schemaPath)
|
|
448
|
+
paths.unshift(schemaPath);
|
|
449
|
+
});
|
|
422
450
|
try {
|
|
423
|
-
const
|
|
451
|
+
const authConfig = await loadAuthOptions(context);
|
|
452
|
+
if (!authConfig)
|
|
453
|
+
return;
|
|
454
|
+
const { userConfig, plugins } = authConfig;
|
|
424
455
|
const userHasSecondaryStorage = userConfig.secondaryStorage != null;
|
|
425
456
|
const secondaryStorageResolution = resolveSchemaSecondaryStorageInjection(hubSecondaryStorage, userHasSecondaryStorage, !nuxt.options.dev);
|
|
426
457
|
if (secondaryStorageResolution.error)
|
|
@@ -458,12 +489,6 @@ async function setupBetterAuthSchema(nuxt, serverConfigPath, options, consola, h
|
|
|
458
489
|
addTemplate({ filename: `better-auth/schema.${dialect}.ts`, getContents: () => schemaCode, write: true });
|
|
459
490
|
addTemplate({ filename: `better-auth/schema.${dialect}.mjs`, getContents: () => schemaCode, write: true });
|
|
460
491
|
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
492
|
} catch (error) {
|
|
468
493
|
const isProduction = !nuxt.options.dev;
|
|
469
494
|
if (isProduction)
|
|
@@ -563,21 +588,24 @@ function resolveDatabaseProvider(input) {
|
|
|
563
588
|
}
|
|
564
589
|
|
|
565
590
|
function resolveSecondaryStorage(input) {
|
|
566
|
-
const { options, clientOnly,
|
|
591
|
+
const { options, clientOnly, consola } = input;
|
|
567
592
|
const opt = options.hubSecondaryStorage ?? false;
|
|
568
|
-
|
|
569
|
-
|
|
593
|
+
if (opt === true) {
|
|
594
|
+
if (clientOnly)
|
|
595
|
+
consola.warn("[nuxt-better-auth] hubSecondaryStorage: true is ignored in clientOnly mode because this module does not run the auth server.");
|
|
596
|
+
else
|
|
597
|
+
consola.warn('[nuxt-better-auth] hubSecondaryStorage: true cannot use NuxtHub KV with Better Auth 1.7 because NuxtHub KV lacks atomic getAndDelete and increment operations. The module will ignore this option and continue without injecting secondary storage. Without a custom secondary store, sessions use the configured database when one exists and rate limiting defaults to process-local memory. Configure rateLimit.storage as "database" or provide rateLimit.customStorage for shared limits. Set auth.hubSecondaryStorage to false to silence this warning, or use "custom" with an atomic secondaryStorage in defineServerAuth(). Track NuxtHub support: https://github.com/nuxt-hub/core/pull/927');
|
|
598
|
+
return { hubSecondaryStorage: false, secondaryStorageEnabled: false };
|
|
599
|
+
}
|
|
600
|
+
const secondaryStorageEnabled = opt === "custom";
|
|
570
601
|
if (secondaryStorageEnabled && clientOnly) {
|
|
571
602
|
throw new Error("[nuxt-better-auth] hubSecondaryStorage is not available in clientOnly mode. Either disable clientOnly or remove auth.hubSecondaryStorage.");
|
|
572
603
|
}
|
|
573
|
-
|
|
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 };
|
|
604
|
+
return { hubSecondaryStorage: opt, secondaryStorageEnabled };
|
|
577
605
|
}
|
|
578
606
|
function setupRuntimeConfig(input) {
|
|
579
607
|
const { nuxt, options, clientOnly, databaseProvider, consola } = input;
|
|
580
|
-
const {
|
|
608
|
+
const { hubSecondaryStorage, secondaryStorageEnabled } = resolveSecondaryStorage(input);
|
|
581
609
|
nuxt.options.runtimeConfig.public = nuxt.options.runtimeConfig.public || {};
|
|
582
610
|
const configuredSiteUrl = nuxt.options.runtimeConfig.public.siteUrl;
|
|
583
611
|
nuxt.options.runtimeConfig.public.siteUrl = configuredSiteUrl || process.env.NUXT_PUBLIC_SITE_URL || "";
|
|
@@ -599,27 +627,44 @@ function setupRuntimeConfig(input) {
|
|
|
599
627
|
if (!siteUrl)
|
|
600
628
|
consola.warn("clientOnly mode: set runtimeConfig.public.siteUrl (or NUXT_PUBLIC_SITE_URL) to your frontend URL");
|
|
601
629
|
consola.info("clientOnly mode enabled - server utilities (serverAuth, getRequestSession, getUserSession, requireUserSession) are not available");
|
|
602
|
-
return {
|
|
630
|
+
return { secondaryStorageEnabled };
|
|
603
631
|
}
|
|
604
632
|
const currentSecret = nuxt.options.runtimeConfig.betterAuthSecret;
|
|
605
633
|
nuxt.options.runtimeConfig.betterAuthSecret = currentSecret || process.env.NUXT_BETTER_AUTH_SECRET || process.env.BETTER_AUTH_SECRET || "";
|
|
606
|
-
|
|
607
|
-
hubSecondaryStorage
|
|
634
|
+
const authRuntimeConfig = defu(nuxt.options.runtimeConfig.auth, {
|
|
635
|
+
hubSecondaryStorage
|
|
608
636
|
});
|
|
609
|
-
|
|
637
|
+
authRuntimeConfig.hubSecondaryStorage = hubSecondaryStorage;
|
|
638
|
+
nuxt.options.runtimeConfig.auth = authRuntimeConfig;
|
|
639
|
+
return { secondaryStorageEnabled };
|
|
610
640
|
}
|
|
611
641
|
|
|
612
|
-
function
|
|
613
|
-
if (!useHubKV)
|
|
614
|
-
return "export function createSecondaryStorage() { return undefined }";
|
|
615
|
-
return `import { kv } from '@nuxthub/kv'
|
|
616
|
-
export function createSecondaryStorage() {
|
|
642
|
+
function buildImports(sources) {
|
|
617
643
|
return {
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
644
|
+
imports: sources.map((source, index) => `import plugin${index} from ${JSON.stringify(source)}`).join("\n"),
|
|
645
|
+
names: sources.map((_, index) => `plugin${index}`).join(", ")
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
function buildExtendedServerAuthCode(configPath, sources) {
|
|
649
|
+
const plugins = buildImports(sources);
|
|
650
|
+
return `import createAppAuth from ${JSON.stringify(configPath)}
|
|
651
|
+
import { extendServerAuth } from '@nuxtjs/better-auth/config'
|
|
652
|
+
${plugins.imports}
|
|
653
|
+
|
|
654
|
+
export default extendServerAuth(createAppAuth, [${plugins.names}])
|
|
655
|
+
`;
|
|
656
|
+
}
|
|
657
|
+
function buildExtendedClientAuthCode(configPath, sources) {
|
|
658
|
+
const plugins = buildImports(sources);
|
|
659
|
+
return `import createAppAuthClient from ${JSON.stringify(configPath)}
|
|
660
|
+
import { extendClientAuth } from '@nuxtjs/better-auth/config'
|
|
661
|
+
${plugins.imports}
|
|
662
|
+
|
|
663
|
+
export default extendClientAuth(createAppAuthClient, [${plugins.names}])
|
|
664
|
+
`;
|
|
665
|
+
}
|
|
666
|
+
function buildSecondaryStorageCode() {
|
|
667
|
+
return "export function createSecondaryStorage() { return undefined }";
|
|
623
668
|
}
|
|
624
669
|
function buildDatabaseCode(input) {
|
|
625
670
|
if (input.provider === "nuxthub") {
|
|
@@ -813,6 +858,9 @@ async function resolveAuthModuleSetup(input, dependencies = {}) {
|
|
|
813
858
|
configExists: dependencies.configExists
|
|
814
859
|
});
|
|
815
860
|
assertConfigPresence(configs, clientOnly);
|
|
861
|
+
const pluginSources = resolveAuthPluginSources(nuxt);
|
|
862
|
+
pluginSources.server.push(...input.registeredPluginSources?.server || []);
|
|
863
|
+
pluginSources.client.push(...input.registeredPluginSources?.client || []);
|
|
816
864
|
const aliases = {
|
|
817
865
|
"#auth/server": clientOnly ? void 0 : configs.server.path,
|
|
818
866
|
"#auth/client": configs.client.path
|
|
@@ -850,13 +898,8 @@ async function resolveAuthModuleSetup(input, dependencies = {}) {
|
|
|
850
898
|
options,
|
|
851
899
|
clientOnly,
|
|
852
900
|
databaseProvider: providerId,
|
|
853
|
-
hasNuxtHub,
|
|
854
|
-
hub,
|
|
855
901
|
consola
|
|
856
902
|
});
|
|
857
|
-
if (runtime.useHubKV && !nuxt.options.alias["hub:kv"]) {
|
|
858
|
-
throw new Error("[nuxt-better-auth] hub:kv not found. Ensure @nuxthub/core is loaded before this module and hub.kv is enabled.");
|
|
859
|
-
}
|
|
860
903
|
const hasHubDb = providerId === "nuxthub";
|
|
861
904
|
if (hasHubDb && !nuxt.options.alias["hub:db"]) {
|
|
862
905
|
throw new Error("[nuxt-better-auth] hub:db not found. Ensure @nuxthub/core is loaded before this module and hub.db is configured.");
|
|
@@ -865,6 +908,7 @@ async function resolveAuthModuleSetup(input, dependencies = {}) {
|
|
|
865
908
|
clientOnly,
|
|
866
909
|
configs,
|
|
867
910
|
aliases,
|
|
911
|
+
pluginSources,
|
|
868
912
|
hub: {
|
|
869
913
|
hasNuxtHub,
|
|
870
914
|
options: hub,
|
|
@@ -912,12 +956,7 @@ function registerServerTypeTemplates(input) {
|
|
|
912
956
|
filename: "types/auth-secondary-storage.d.ts",
|
|
913
957
|
getContents: () => `
|
|
914
958
|
declare module '#auth/secondary-storage' {
|
|
915
|
-
|
|
916
|
-
get: (key: string) => Promise<string | null>
|
|
917
|
-
set: (key: string, value: unknown, ttl?: number) => Promise<void>
|
|
918
|
-
delete: (key: string) => Promise<void>
|
|
919
|
-
}
|
|
920
|
-
export function createSecondaryStorage(): SecondaryStorage | undefined
|
|
959
|
+
export function createSecondaryStorage(): undefined
|
|
921
960
|
}
|
|
922
961
|
`
|
|
923
962
|
}, { nitro: true });
|
|
@@ -1371,94 +1410,122 @@ const module$1 = defineNuxtModule({
|
|
|
1371
1410
|
process.env.NUXT_BETTER_AUTH_SECRET = generatedSecret;
|
|
1372
1411
|
await createDefaultAuthConfigFiles(nuxt);
|
|
1373
1412
|
},
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
write: true
|
|
1392
|
-
});
|
|
1393
|
-
nuxt.options.alias["#auth/secondary-storage"] = secondaryStorageTemplate.dst;
|
|
1394
|
-
const databaseTemplate = addTemplate({
|
|
1395
|
-
filename: "better-auth/database.mjs",
|
|
1396
|
-
getContents: () => setup.database.providerDefinition.buildDatabaseCode(setup.database.buildContext),
|
|
1397
|
-
write: true
|
|
1413
|
+
setup(options, nuxt) {
|
|
1414
|
+
nuxt.hook("modules:done", async () => {
|
|
1415
|
+
const resolver = createResolver(import.meta.url);
|
|
1416
|
+
const nitroImports = resolveNitroCompatibilityImports(nuxt._version);
|
|
1417
|
+
nuxt.options.alias["#better-auth/nitro-compat"] = resolver.resolve(`./runtime/server/internal/${nitroImports.runtime}`);
|
|
1418
|
+
const registeredPluginSources = {};
|
|
1419
|
+
await nuxt.callHook("better-auth:plugins:extend", registeredPluginSources);
|
|
1420
|
+
for (const source of [...registeredPluginSources.server || [], ...registeredPluginSources.client || []]) {
|
|
1421
|
+
if (!isAbsolute(source))
|
|
1422
|
+
throw new Error(`[nuxt-better-auth] Modules must register absolute plugin source paths. Received: ${source}`);
|
|
1423
|
+
}
|
|
1424
|
+
const setup = await resolveAuthModuleSetup({
|
|
1425
|
+
nuxt,
|
|
1426
|
+
options,
|
|
1427
|
+
runtimeTypesAugmentPath: resolver.resolve("./runtime/types/augment"),
|
|
1428
|
+
consola,
|
|
1429
|
+
registeredPluginSources
|
|
1398
1430
|
});
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1431
|
+
let serverConfigPath = setup.aliases["#auth/server"];
|
|
1432
|
+
let clientConfigPath = setup.aliases["#auth/client"];
|
|
1433
|
+
if (serverConfigPath && setup.pluginSources.server.length) {
|
|
1434
|
+
const serverConfigCode = buildExtendedServerAuthCode(setup.configs.server.path, setup.pluginSources.server);
|
|
1435
|
+
serverConfigPath = addTemplate({
|
|
1436
|
+
filename: "better-auth/server.config.ts",
|
|
1437
|
+
getContents: () => serverConfigCode,
|
|
1438
|
+
write: true
|
|
1439
|
+
}).dst;
|
|
1440
|
+
await mkdir(dirname(serverConfigPath), { recursive: true });
|
|
1441
|
+
await writeFile(serverConfigPath, serverConfigCode);
|
|
1442
|
+
}
|
|
1443
|
+
if (setup.pluginSources.client.length) {
|
|
1444
|
+
clientConfigPath = addTemplate({
|
|
1445
|
+
filename: "better-auth/client.config.ts",
|
|
1446
|
+
getContents: () => buildExtendedClientAuthCode(setup.configs.client.path, setup.pluginSources.client),
|
|
1447
|
+
write: true
|
|
1448
|
+
}).dst;
|
|
1449
|
+
}
|
|
1450
|
+
if (serverConfigPath)
|
|
1451
|
+
nuxt.options.alias["#auth/server"] = serverConfigPath;
|
|
1452
|
+
nuxt.options.alias["#auth/client"] = clientConfigPath;
|
|
1453
|
+
if (!setup.clientOnly) {
|
|
1454
|
+
const secondaryStorageTemplate = addTemplate({
|
|
1455
|
+
filename: "better-auth/secondary-storage.mjs",
|
|
1456
|
+
getContents: () => buildSecondaryStorageCode(),
|
|
1457
|
+
write: true
|
|
1458
|
+
});
|
|
1459
|
+
nuxt.options.alias["#auth/secondary-storage"] = secondaryStorageTemplate.dst;
|
|
1460
|
+
const databaseTemplate = addTemplate({
|
|
1461
|
+
filename: "better-auth/database.mjs",
|
|
1462
|
+
getContents: () => setup.database.providerDefinition.buildDatabaseCode(setup.database.buildContext),
|
|
1463
|
+
write: true
|
|
1464
|
+
});
|
|
1465
|
+
nuxt.options.alias["#auth/database"] = databaseTemplate.dst;
|
|
1466
|
+
const schemaTemplate = addTemplate({
|
|
1467
|
+
filename: "better-auth/schema.mjs",
|
|
1468
|
+
getContents: () => buildSchemaExportCode(setup.database.hasHubDb, setup.database.buildContext?.hubDialect ?? "sqlite"),
|
|
1469
|
+
write: true
|
|
1470
|
+
});
|
|
1471
|
+
nuxt.options.alias["#auth/schema"] = schemaTemplate.dst;
|
|
1472
|
+
if (setup.schemaGeneration)
|
|
1473
|
+
await ensureSchemaBootstrap(schemaTemplate.dst, setup.database.buildContext?.hubDialect ?? "sqlite");
|
|
1474
|
+
}
|
|
1475
|
+
if (setup.prepareTypes) {
|
|
1476
|
+
registerPrepareTypesHook({
|
|
1477
|
+
nuxt,
|
|
1478
|
+
serverDir: setup.prepareTypes.serverDir,
|
|
1479
|
+
hasHubDb: setup.prepareTypes.hasHubDb
|
|
1480
|
+
});
|
|
1481
|
+
}
|
|
1482
|
+
if (setup.database.providerDefinition) {
|
|
1483
|
+
const setupCtx = {
|
|
1484
|
+
nuxt,
|
|
1485
|
+
options,
|
|
1486
|
+
clientOnly: setup.clientOnly
|
|
1487
|
+
};
|
|
1488
|
+
await setup.database.providerDefinition.setup?.(setupCtx);
|
|
1489
|
+
}
|
|
1490
|
+
const authRouteRulesTemplate = addTemplate({
|
|
1491
|
+
filename: "better-auth/route-rules.mjs",
|
|
1492
|
+
getContents: () => buildAuthRouteRulesCode(collectAuthRouteRules(nuxt)),
|
|
1403
1493
|
write: true
|
|
1404
1494
|
});
|
|
1405
|
-
nuxt.options.alias["#auth/
|
|
1406
|
-
if (setup.
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
nuxt.options.alias["#auth/route-rules"] = authRouteRulesTemplate.dst;
|
|
1430
|
-
if (setup.serverTypes) {
|
|
1431
|
-
registerServerTypeTemplates({
|
|
1432
|
-
serverConfigPath: setup.serverTypes.serverConfigPath,
|
|
1433
|
-
hasHubDb: setup.serverTypes.hasHubDb,
|
|
1495
|
+
nuxt.options.alias["#auth/route-rules"] = authRouteRulesTemplate.dst;
|
|
1496
|
+
if (setup.serverTypes) {
|
|
1497
|
+
registerServerTypeTemplates({
|
|
1498
|
+
serverConfigPath,
|
|
1499
|
+
hasHubDb: setup.serverTypes.hasHubDb,
|
|
1500
|
+
runtimeTypesPath: resolver.resolve("./runtime/types"),
|
|
1501
|
+
sharedServerConfigSafe: [setup.configs.server.path, ...setup.pluginSources.server].every(isServerConfigSharedTypeSafe),
|
|
1502
|
+
h3TypesPath: nitroImports.h3,
|
|
1503
|
+
nitroTypesPath: nitroImports.types
|
|
1504
|
+
});
|
|
1505
|
+
}
|
|
1506
|
+
if (setup.schemaGeneration) {
|
|
1507
|
+
if (setup.schemaGeneration.externalizeNuxtHubDatabase)
|
|
1508
|
+
registerNuxtHubDatabaseExternalHook(nuxt);
|
|
1509
|
+
await setupBetterAuthSchema(
|
|
1510
|
+
nuxt,
|
|
1511
|
+
serverConfigPath,
|
|
1512
|
+
options,
|
|
1513
|
+
consola,
|
|
1514
|
+
setup.schemaGeneration.hubSecondaryStorage
|
|
1515
|
+
);
|
|
1516
|
+
}
|
|
1517
|
+
registerSharedTypeTemplates({
|
|
1518
|
+
runtimeTypesAugmentPath: setup.sharedTypes.runtimeTypesAugmentPath,
|
|
1434
1519
|
runtimeTypesPath: resolver.resolve("./runtime/types"),
|
|
1435
|
-
|
|
1436
|
-
h3TypesPath: nitroImports.h3
|
|
1437
|
-
nitroTypesPath: nitroImports.types
|
|
1520
|
+
clientConfigPath,
|
|
1521
|
+
h3TypesPath: nitroImports.h3
|
|
1438
1522
|
});
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
nuxt,
|
|
1445
|
-
setup.schemaGeneration.serverConfigPath,
|
|
1446
|
-
options,
|
|
1447
|
-
consola,
|
|
1448
|
-
setup.schemaGeneration.hubSecondaryStorage
|
|
1449
|
-
);
|
|
1450
|
-
}
|
|
1451
|
-
registerSharedTypeTemplates({
|
|
1452
|
-
runtimeTypesAugmentPath: setup.sharedTypes.runtimeTypesAugmentPath,
|
|
1453
|
-
runtimeTypesPath: resolver.resolve("./runtime/types"),
|
|
1454
|
-
clientConfigPath: setup.sharedTypes.clientConfigPath,
|
|
1455
|
-
h3TypesPath: nitroImports.h3
|
|
1523
|
+
registerTemplateHmrHook(nuxt);
|
|
1524
|
+
registerServerRuntime({ clientOnly: setup.clientOnly, resolve: resolver.resolve });
|
|
1525
|
+
registerAuthMiddlewareHook(nuxt, resolver.resolve);
|
|
1526
|
+
await registerDevtools({ nuxt, clientOnly: setup.clientOnly, hasHubDb: setup.database.hasHubDb, resolve: resolver.resolve });
|
|
1527
|
+
registerRouteRulesMetaHook(nuxt);
|
|
1456
1528
|
});
|
|
1457
|
-
registerTemplateHmrHook(nuxt);
|
|
1458
|
-
registerServerRuntime({ clientOnly: setup.clientOnly, resolve: resolver.resolve });
|
|
1459
|
-
registerAuthMiddlewareHook(nuxt, resolver.resolve);
|
|
1460
|
-
await registerDevtools({ nuxt, clientOnly: setup.clientOnly, hasHubDb: setup.database.hasHubDb, resolve: resolver.resolve });
|
|
1461
|
-
registerRouteRulesMetaHook(nuxt);
|
|
1462
1529
|
}
|
|
1463
1530
|
});
|
|
1464
1531
|
|
|
@@ -87,8 +87,21 @@ export function useUserSession() {
|
|
|
87
87
|
throw error;
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
|
+
function queueHydrationReconciliation() {
|
|
91
|
+
if (hydrationReconcileQueued.value)
|
|
92
|
+
return;
|
|
93
|
+
hydrationReconcileQueued.value = true;
|
|
94
|
+
nuxtApp.hook("app:mounted", async () => {
|
|
95
|
+
await fetchSession({ force: true });
|
|
96
|
+
hydrationReconcileQueued.value = false;
|
|
97
|
+
});
|
|
98
|
+
}
|
|
90
99
|
if (runtimeFlags.client && rawClient) {
|
|
91
100
|
const clientSession = rawClient.useSession();
|
|
101
|
+
const initialClientSession = clientSession.value;
|
|
102
|
+
const shouldReconcileInitialHydration = nuxtApp.isHydrating && nuxtApp.payload.serverRendered && Boolean(session.value && user.value) && !initialClientSession?.data?.session && !initialClientSession?.data?.user && !initialClientSession?.isPending && !initialClientSession?.isRefetching;
|
|
103
|
+
if (shouldReconcileInitialHydration)
|
|
104
|
+
queueHydrationReconciliation();
|
|
92
105
|
watch(
|
|
93
106
|
() => clientSession.value,
|
|
94
107
|
(newSession) => {
|
|
@@ -101,21 +114,14 @@ export function useUserSession() {
|
|
|
101
114
|
} else if (!newSession?.isPending && !newSession?.isRefetching) {
|
|
102
115
|
const isHydrationEmptySnapshot = nuxtApp.isHydrating && nuxtApp.payload.serverRendered && Boolean(session.value && user.value) && !newSession?.data?.session && !newSession?.data?.user;
|
|
103
116
|
if (isHydrationEmptySnapshot) {
|
|
104
|
-
|
|
105
|
-
hydrationReconcileQueued.value = true;
|
|
106
|
-
nuxtApp.hook("app:mounted", async () => {
|
|
107
|
-
await fetchSession({ force: true });
|
|
108
|
-
hydrationReconcileQueued.value = false;
|
|
109
|
-
});
|
|
110
|
-
}
|
|
117
|
+
queueHydrationReconciliation();
|
|
111
118
|
return;
|
|
112
119
|
}
|
|
113
120
|
clearSession();
|
|
114
121
|
}
|
|
115
122
|
if (!authReady.value && !newSession?.isPending && !newSession?.isRefetching)
|
|
116
123
|
authReady.value = true;
|
|
117
|
-
}
|
|
118
|
-
{ immediate: true }
|
|
124
|
+
}
|
|
119
125
|
);
|
|
120
126
|
}
|
|
121
127
|
function waitForSession() {
|
package/dist/runtime/config.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BetterAuthOptions, BetterAuthPlugin } from 'better-auth';
|
|
2
|
-
import type { BetterAuthClientOptions } from 'better-auth/client';
|
|
2
|
+
import type { BetterAuthClientOptions, BetterAuthClientPlugin } from 'better-auth/client';
|
|
3
3
|
import type { ServerAuthContext as BaseServerAuthContext } from './types/augment.js';
|
|
4
4
|
import { createAuthClient } from 'better-auth/vue';
|
|
5
5
|
export interface ServerAuthContextExtension {
|
|
@@ -17,6 +17,23 @@ export type ClientAuthConfig = Omit<BetterAuthClientOptions, 'baseURL'> & {
|
|
|
17
17
|
};
|
|
18
18
|
export type ServerAuthConfigFn = (ctx: ServerAuthContext) => ServerAuthConfig;
|
|
19
19
|
export type ClientAuthConfigFn = (ctx: ClientAuthContext) => ClientAuthConfig;
|
|
20
|
+
type ServerPlugins<T> = T extends {
|
|
21
|
+
plugins: infer P extends readonly BetterAuthPlugin[];
|
|
22
|
+
} ? P : [];
|
|
23
|
+
type ClientPlugins<T> = T extends {
|
|
24
|
+
plugins: infer P extends BetterAuthClientPlugin[];
|
|
25
|
+
} ? P : [];
|
|
26
|
+
type ExtendedServerAuthConfig<T, P extends readonly BetterAuthPlugin[]> = Omit<T, 'plugins'> & {
|
|
27
|
+
plugins: [...ServerPlugins<T>, ...P];
|
|
28
|
+
};
|
|
29
|
+
type ExtendedClientAuthConfig<T, P extends BetterAuthClientPlugin[]> = Omit<T, 'plugins'> & {
|
|
30
|
+
plugins: [...ClientPlugins<T>, ...P];
|
|
31
|
+
};
|
|
32
|
+
export type ClientAuthFactory<T extends ClientAuthConfig> = ((baseURL: string) => ReturnType<typeof createAuthClient<T>>) & {
|
|
33
|
+
resolveOptions: (baseURL: string) => T & {
|
|
34
|
+
baseURL: string;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
20
37
|
export type ModuleDatabaseProviderId = 'none' | 'nuxthub' | (string & {});
|
|
21
38
|
export type EffectiveDatabaseProviderId = 'user' | ModuleDatabaseProviderId;
|
|
22
39
|
export interface BetterAuthModuleOptions {
|
|
@@ -26,6 +43,10 @@ export interface BetterAuthModuleOptions {
|
|
|
26
43
|
serverConfig?: string;
|
|
27
44
|
/** Client config path. Relative paths resolve from the layer that declares them. Default: 'app/auth.config' */
|
|
28
45
|
clientConfig?: string;
|
|
46
|
+
/** Server plugin modules. Relative paths resolve from the declaring layer. Sources are additive and are not deduplicated. */
|
|
47
|
+
serverPluginSources?: string[];
|
|
48
|
+
/** Client plugin modules. Relative paths resolve from the declaring layer. Sources are additive and are not deduplicated. */
|
|
49
|
+
clientPluginSources?: string[];
|
|
29
50
|
redirects?: {
|
|
30
51
|
/** Where to redirect unauthenticated users. Default: '/login' */
|
|
31
52
|
login?: string;
|
|
@@ -50,9 +71,9 @@ export interface BetterAuthModuleOptions {
|
|
|
50
71
|
*/
|
|
51
72
|
redirectQueryKey?: string;
|
|
52
73
|
/**
|
|
53
|
-
*
|
|
54
|
-
* - `true`:
|
|
55
|
-
* - `'custom'`: User provides
|
|
74
|
+
* Configure secondary storage for sessions.
|
|
75
|
+
* - `true`: Temporarily falls back to database-backed sessions with a setup warning
|
|
76
|
+
* - `'custom'`: User provides an atomic secondaryStorage in defineServerAuth()
|
|
56
77
|
* - `false` (default): No secondary storage from module
|
|
57
78
|
*/
|
|
58
79
|
hubSecondaryStorage?: boolean | 'custom';
|
|
@@ -84,4 +105,7 @@ export interface AuthPrivateRuntimeConfig {
|
|
|
84
105
|
}
|
|
85
106
|
export declare function defineServerAuth<const R>(config: (ctx: ServerAuthContext) => R & ServerAuthConfig): (ctx: ServerAuthContext) => R;
|
|
86
107
|
export declare function defineServerAuth<const R>(config: R & ServerAuthConfig): (ctx: ServerAuthContext) => R;
|
|
87
|
-
export declare function
|
|
108
|
+
export declare function extendServerAuth<const R extends ServerAuthConfig, const P extends readonly BetterAuthPlugin[]>(createConfig: (ctx: ServerAuthContext) => R, plugins: P): (ctx: ServerAuthContext) => ExtendedServerAuthConfig<R, P>;
|
|
109
|
+
export declare function defineClientAuth<T extends ClientAuthConfig>(config: T | ((ctx: ClientAuthContext) => T)): ClientAuthFactory<T>;
|
|
110
|
+
export declare function extendClientAuth<T extends ClientAuthConfig, const P extends BetterAuthClientPlugin[]>(createClient: ClientAuthFactory<T>, plugins: P): ClientAuthFactory<ExtendedClientAuthConfig<T, P>>;
|
|
111
|
+
export {};
|
package/dist/runtime/config.js
CHANGED
|
@@ -2,12 +2,30 @@ import { createAuthClient } from "better-auth/vue";
|
|
|
2
2
|
export function defineServerAuth(config) {
|
|
3
3
|
return typeof config === "function" ? config : () => config;
|
|
4
4
|
}
|
|
5
|
+
export function extendServerAuth(createConfig, plugins) {
|
|
6
|
+
return (ctx) => {
|
|
7
|
+
const config = createConfig(ctx);
|
|
8
|
+
const basePlugins = config.plugins || [];
|
|
9
|
+
return { ...config, plugins: [...basePlugins, ...plugins] };
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function createClientAuthFactory(resolveOptions) {
|
|
13
|
+
const factory = ((baseURL) => createAuthClient(resolveOptions(baseURL)));
|
|
14
|
+
factory.resolveOptions = resolveOptions;
|
|
15
|
+
return factory;
|
|
16
|
+
}
|
|
5
17
|
export function defineClientAuth(config) {
|
|
6
|
-
return (baseURL) => {
|
|
18
|
+
return createClientAuthFactory((baseURL) => {
|
|
7
19
|
const ctx = { siteUrl: baseURL };
|
|
8
20
|
const resolved = typeof config === "function" ? config(ctx) : config;
|
|
9
21
|
const { baseURL: configuredBaseURL, ...resolvedOptions } = resolved;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
22
|
+
return { ...resolvedOptions, baseURL: configuredBaseURL ?? baseURL };
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
export function extendClientAuth(createClient, plugins) {
|
|
26
|
+
return createClientAuthFactory((baseURL) => {
|
|
27
|
+
const config = createClient.resolveOptions(baseURL);
|
|
28
|
+
const basePlugins = config.plugins || [];
|
|
29
|
+
return { ...config, plugins: [...basePlugins, ...plugins] };
|
|
30
|
+
});
|
|
13
31
|
}
|
|
@@ -25,7 +25,7 @@ export default defineEventHandler(async (event) => {
|
|
|
25
25
|
},
|
|
26
26
|
preserveRedirect: publicAuth?.preserveRedirect ?? true,
|
|
27
27
|
redirectQueryKey: publicAuth?.redirectQueryKey ?? "redirect",
|
|
28
|
-
hubSecondaryStorage: privateAuth?.hubSecondaryStorage ?? false,
|
|
28
|
+
hubSecondaryStorage: privateAuth?.hubSecondaryStorage === true ? false : privateAuth?.hubSecondaryStorage ?? false,
|
|
29
29
|
useDatabase: publicAuth?.useDatabase ?? false,
|
|
30
30
|
databaseProvider: publicAuth?.databaseProvider ?? "none"
|
|
31
31
|
},
|
|
@@ -4,6 +4,7 @@ import { betterAuth } from 'better-auth';
|
|
|
4
4
|
import createServerAuth from '#auth/server';
|
|
5
5
|
type AuthOptions = ReturnType<typeof createServerAuth>;
|
|
6
6
|
type UserAuthConfig = AuthOptions & {
|
|
7
|
+
rateLimit?: BetterAuthOptions['rateLimit'];
|
|
7
8
|
secrets?: BetterAuthOptions['secrets'];
|
|
8
9
|
trustedOrigins?: BetterAuthOptions['trustedOrigins'];
|
|
9
10
|
secondaryStorage?: BetterAuthOptions['secondaryStorage'];
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { betterAuth, env } from "better-auth";
|
|
2
2
|
import { withoutProtocol } from "ufo";
|
|
3
3
|
import { createDatabase, db } from "#auth/database";
|
|
4
|
-
import { createSecondaryStorage } from "#auth/secondary-storage";
|
|
5
4
|
import createServerAuth from "#auth/server";
|
|
6
5
|
import { getRequestHost, getRequestProtocol, useRuntimeConfig } from "../internal/nitro-compat.js";
|
|
7
6
|
import { resolveCustomSecondaryStorageRequirement } from "./custom-secondary-storage.js";
|
|
@@ -9,6 +8,8 @@ const _authCache = /* @__PURE__ */ new Map();
|
|
|
9
8
|
const requestAuthKey = Symbol.for("nuxt-better-auth.requestAuth");
|
|
10
9
|
let _baseURLInferenceLogged = false;
|
|
11
10
|
let _customSecondaryStorageMisconfigWarned = false;
|
|
11
|
+
let _unsupportedHubSecondaryStorageWarned = false;
|
|
12
|
+
let _secondaryStorageRateLimitFallbackWarned = false;
|
|
12
13
|
const fallbackRequestAuthContext = /* @__PURE__ */ new WeakMap();
|
|
13
14
|
function getRequestAuthContext(event) {
|
|
14
15
|
const eventWithContext = event;
|
|
@@ -214,6 +215,10 @@ export function serverAuth(event) {
|
|
|
214
215
|
const database = createDatabase(event);
|
|
215
216
|
const trustedOrigins = withDevTrustedOrigins(userConfig.trustedOrigins);
|
|
216
217
|
const hubSecondaryStorage = runtimeConfig.auth?.hubSecondaryStorage;
|
|
218
|
+
if (hubSecondaryStorage === true && !_unsupportedHubSecondaryStorageWarned) {
|
|
219
|
+
_unsupportedHubSecondaryStorageWarned = true;
|
|
220
|
+
console.warn("[nuxt-better-auth] Runtime hubSecondaryStorage: true is unsupported with Better Auth 1.7 and will be ignored. The module will preserve secondaryStorage from defineServerAuth(). Remove NUXT_AUTH_HUB_SECONDARY_STORAGE or set it to false.");
|
|
221
|
+
}
|
|
217
222
|
const customSecondaryStorage = resolveCustomSecondaryStorageRequirement(hubSecondaryStorage, userConfig.secondaryStorage != null, Boolean(import.meta.dev));
|
|
218
223
|
if (customSecondaryStorage?.shouldThrow)
|
|
219
224
|
throw new Error(customSecondaryStorage.message);
|
|
@@ -221,6 +226,12 @@ export function serverAuth(event) {
|
|
|
221
226
|
_customSecondaryStorageMisconfigWarned = true;
|
|
222
227
|
console.warn(customSecondaryStorage.message);
|
|
223
228
|
}
|
|
229
|
+
const useMemoryRateLimit = userConfig.rateLimit?.storage === "secondary-storage" && !userConfig.rateLimit.customStorage && !userConfig.secondaryStorage;
|
|
230
|
+
if (useMemoryRateLimit && !_secondaryStorageRateLimitFallbackWarned) {
|
|
231
|
+
_secondaryStorageRateLimitFallbackWarned = true;
|
|
232
|
+
console.warn('[nuxt-better-auth] rateLimit.storage: "secondary-storage" requires secondaryStorage. Falling back to process-local memory. Set rateLimit.storage to "database" or provide rateLimit.customStorage for shared limits.');
|
|
233
|
+
}
|
|
234
|
+
const rateLimit = useMemoryRateLimit ? { ...userConfig.rateLimit, storage: "memory" } : userConfig.rateLimit;
|
|
224
235
|
if (!database) {
|
|
225
236
|
const cached = _authCache.get(cacheKey);
|
|
226
237
|
if (cached) {
|
|
@@ -231,8 +242,8 @@ export function serverAuth(event) {
|
|
|
231
242
|
}
|
|
232
243
|
const authOptions = {
|
|
233
244
|
...userConfig,
|
|
245
|
+
...rateLimit ? { rateLimit } : {},
|
|
234
246
|
...database ? { database } : {},
|
|
235
|
-
...hubSecondaryStorage === true ? { secondaryStorage: createSecondaryStorage() } : {},
|
|
236
247
|
secret: betterAuthSecret,
|
|
237
248
|
baseURL: siteUrl,
|
|
238
249
|
trustedOrigins
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuxtjs/better-auth",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.3",
|
|
5
5
|
"description": "Nuxt module for Better Auth integration with NuxtHub, route protection, session management, and role-based access",
|
|
6
6
|
"author": "onmax",
|
|
7
7
|
"license": "MIT",
|