@onmax/nuxt-better-auth 0.0.2-alpha.29 → 0.0.2-alpha.30
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 +1 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +208 -7
- package/dist/runtime/app/composables/useAction.d.ts +2 -0
- package/dist/runtime/app/composables/useAction.js +6 -0
- package/dist/runtime/app/composables/useAuthAsyncData.d.ts +6 -0
- package/dist/runtime/app/composables/useAuthAsyncData.js +16 -0
- package/dist/runtime/app/composables/useAuthClientAction.d.ts +5 -0
- package/dist/runtime/app/composables/useAuthClientAction.js +15 -0
- package/dist/runtime/app/composables/useAuthRequestFetch.d.ts +11 -0
- package/dist/runtime/app/composables/useAuthRequestFetch.js +4 -0
- package/dist/runtime/app/composables/useSignIn.d.ts +16 -0
- package/dist/runtime/app/composables/{useUserSignIn.js → useSignIn.js} +2 -2
- package/dist/runtime/app/composables/{useUserSignUp.d.ts → useSignUp.d.ts} +1 -1
- package/dist/runtime/app/composables/{useUserSignUp.js → useSignUp.js} +2 -2
- package/dist/runtime/app/composables/useUserSession.js +84 -10
- package/dist/runtime/app/internal/auth-action-error.d.ts +1 -0
- package/dist/runtime/app/internal/auth-action-error.js +2 -1
- package/dist/runtime/app/internal/auth-action-handles.d.ts +4 -0
- package/dist/runtime/app/internal/auth-action-handles.js +31 -1
- package/dist/runtime/app/middleware/auth.global.js +34 -9
- package/dist/runtime/server/api/_better-auth/config.get.d.ts +9 -9
- package/dist/runtime/server/utils/auth.d.ts +3 -1
- package/dist/runtime/server/utils/session.d.ts +1 -1
- package/dist/runtime/server/utils/session.js +18 -18
- package/dist/runtime/types/augment.d.ts +2 -0
- package/dist/runtime/types.d.ts +5 -2
- package/dist/types.d.mts +1 -1
- package/package.json +23 -37
- package/dist/runtime/app/composables/useUserSignIn.d.ts +0 -5
package/dist/module.d.mts
CHANGED
|
@@ -3,7 +3,7 @@ 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
5
|
import { BetterAuthOptions } from 'better-auth';
|
|
6
|
-
export { AppSession, Auth, AuthActionError, AuthMeta, AuthMode, AuthRouteRules, AuthSession, AuthUser, InferSession, InferUser, RequireSessionOptions, ServerAuthContext, UserMatch } from '../dist/runtime/types.js';
|
|
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
|
interface RuntimeDefineServerAuthFn {
|
|
9
9
|
(...args: unknown[]): unknown;
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -10,7 +10,7 @@ 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.30";
|
|
14
14
|
|
|
15
15
|
function resolveDatabaseProvider(input) {
|
|
16
16
|
const enabledProviders = Object.entries(input.providers).filter(([_id, provider]) => provider.isEnabled?.(input.context) ?? true);
|
|
@@ -88,7 +88,8 @@ async function registerDevtools(input) {
|
|
|
88
88
|
}
|
|
89
89
|
function registerRouteRulesMetaHook(nuxt) {
|
|
90
90
|
nuxt.hook("pages:extend", (pages) => {
|
|
91
|
-
const
|
|
91
|
+
const options = nuxt.options;
|
|
92
|
+
const routeRules = options.nitro?.routeRules || options.routeRules || {};
|
|
92
93
|
if (!Object.keys(routeRules).length)
|
|
93
94
|
return;
|
|
94
95
|
const matcher = toRouteMatcher(createRouter({ routes: routeRules }));
|
|
@@ -162,7 +163,7 @@ function setupRuntimeConfig(input) {
|
|
|
162
163
|
const siteUrl = nuxt.options.runtimeConfig.public.siteUrl;
|
|
163
164
|
if (!siteUrl)
|
|
164
165
|
consola.warn("clientOnly mode: set runtimeConfig.public.siteUrl (or NUXT_PUBLIC_SITE_URL) to your frontend URL");
|
|
165
|
-
consola.info("clientOnly mode enabled - server utilities (serverAuth,
|
|
166
|
+
consola.info("clientOnly mode enabled - server utilities (serverAuth, getRequestSession, getUserSession, requireUserSession) are not available");
|
|
166
167
|
return { useHubKV, secondaryStorageEnabled };
|
|
167
168
|
}
|
|
168
169
|
const currentSecret = nuxt.options.runtimeConfig.betterAuthSecret;
|
|
@@ -203,7 +204,10 @@ async function generateDrizzleSchema(authOptions, dialect, schemaOptions) {
|
|
|
203
204
|
adapterConfig: { usePlural: schemaOptions?.usePlural ?? false }
|
|
204
205
|
}
|
|
205
206
|
};
|
|
206
|
-
const result = await generateDrizzleSchema$1({
|
|
207
|
+
const result = await generateDrizzleSchema$1({
|
|
208
|
+
adapter,
|
|
209
|
+
options
|
|
210
|
+
});
|
|
207
211
|
if (!result.code) {
|
|
208
212
|
throw new Error(`Schema generation returned empty result for ${dialect}`);
|
|
209
213
|
}
|
|
@@ -254,7 +258,7 @@ async function loadUserAuthConfig(configPath, throwOnError = false) {
|
|
|
254
258
|
|
|
255
259
|
function resolveSchemaSecondaryStorageInjection(hubSecondaryStorage, userHasSecondaryStorage, isProduction) {
|
|
256
260
|
if (hubSecondaryStorage === true)
|
|
257
|
-
return { inject:
|
|
261
|
+
return { inject: false };
|
|
258
262
|
if (hubSecondaryStorage !== "custom")
|
|
259
263
|
return { inject: false };
|
|
260
264
|
if (userHasSecondaryStorage)
|
|
@@ -541,11 +545,191 @@ declare module '@onmax/nuxt-better-auth/config' {
|
|
|
541
545
|
export function defineServerAuth<const R>(config: (ctx: _AugmentedServerAuthContext) => R & ServerAuthConfig): (ctx: _AugmentedServerAuthContext) => R
|
|
542
546
|
export function defineServerAuth<const R>(config: R & ServerAuthConfig): (ctx: _AugmentedServerAuthContext) => R
|
|
543
547
|
}
|
|
548
|
+
`
|
|
549
|
+
}, { nuxt: true, nitro: true, node: true });
|
|
550
|
+
addTypeTemplate({
|
|
551
|
+
filename: "types/nuxt-better-auth-social-providers.d.ts",
|
|
552
|
+
getContents: () => `
|
|
553
|
+
import type createServerAuth from '${serverConfigPath}'
|
|
554
|
+
|
|
555
|
+
type _RawConfig = ReturnType<typeof createServerAuth>
|
|
556
|
+
type _RawSocialProviders = _RawConfig extends { socialProviders: infer S } ? S : _RawConfig extends { socialProviders?: infer S } ? S : {}
|
|
557
|
+
type _SocialProviderIds = Extract<keyof NonNullable<_RawSocialProviders>, string>
|
|
558
|
+
|
|
559
|
+
declare module '#nuxt-better-auth' {
|
|
560
|
+
interface AuthSocialProviderRegistry {
|
|
561
|
+
ids: _SocialProviderIds
|
|
562
|
+
}
|
|
563
|
+
}
|
|
544
564
|
`
|
|
545
565
|
}, { nuxt: true, nitro: true, node: true });
|
|
546
566
|
addTypeTemplate({
|
|
547
567
|
filename: "types/nuxt-better-auth-nitro.d.ts",
|
|
548
568
|
getContents: () => `
|
|
569
|
+
import type createServerAuth from '${serverConfigPath}'
|
|
570
|
+
import type { BetterAuthOptions } from 'better-auth'
|
|
571
|
+
import type { getEndpoints } from 'better-auth/api'
|
|
572
|
+
import type { Serialize, Simplify } from 'nitropack/types'
|
|
573
|
+
import type { FetchError } from 'ofetch'
|
|
574
|
+
|
|
575
|
+
type _RawConfig = ReturnType<typeof createServerAuth>
|
|
576
|
+
type _RawPlugins = _RawConfig extends { plugins: infer P } ? P : _RawConfig extends { plugins?: infer P } ? P : []
|
|
577
|
+
type _Config = Omit<BetterAuthOptions, 'plugins'> & Omit<_RawConfig, 'plugins'> & {
|
|
578
|
+
plugins?: _RawPlugins
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
type _AuthApi = ReturnType<typeof getEndpoints<_Config>>['api']
|
|
582
|
+
type _NormalizeMethod<M extends string> = M extends '*' ? 'default' : Lowercase<M>
|
|
583
|
+
type _RouteMethodFromOption<M> = M extends readonly (infer T)[]
|
|
584
|
+
? _NormalizeMethod<Extract<T, string>>
|
|
585
|
+
: M extends string
|
|
586
|
+
? _NormalizeMethod<M>
|
|
587
|
+
: 'default'
|
|
588
|
+
type _RouteMethodFromEndpoint<E> = E extends { options: { method: infer M } } ? _RouteMethodFromOption<M> : 'default'
|
|
589
|
+
type _RoutePathFromEndpoint<E> = E extends { path: infer P extends string }
|
|
590
|
+
? string extends P
|
|
591
|
+
? never
|
|
592
|
+
: \`/api/auth\${P}\`
|
|
593
|
+
: never
|
|
594
|
+
type _RouteResponseFromEndpoint<E> = E extends (...args: any[]) => Promise<infer R> ? Simplify<Serialize<Awaited<R>>> : never
|
|
595
|
+
type _RouteDefaultResponse<E> = never
|
|
596
|
+
type _UnionToIntersection<U> = (U extends unknown ? (value: U) => void : never) extends (value: infer I) => void ? I : never
|
|
597
|
+
|
|
598
|
+
type _CoreAuthInternalApi = {
|
|
599
|
+
[K in keyof _AuthApi as _RoutePathFromEndpoint<_AuthApi[K]>]: {
|
|
600
|
+
[M in _RouteMethodFromEndpoint<_AuthApi[K]> | 'default']: M extends 'default' ? _RouteDefaultResponse<_AuthApi[K]> : _RouteResponseFromEndpoint<_AuthApi[K]>
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
type _PluginEndpointMaps<Plugins> = Plugins extends readonly (infer Plugin)[]
|
|
604
|
+
? Plugin extends { endpoints: infer Endpoints extends Record<string, unknown> }
|
|
605
|
+
? {
|
|
606
|
+
[K in keyof Endpoints as _RoutePathFromEndpoint<Endpoints[K]>]: {
|
|
607
|
+
[M in _RouteMethodFromEndpoint<Endpoints[K]> | 'default']: M extends 'default' ? _RouteDefaultResponse<Endpoints[K]> : _RouteResponseFromEndpoint<Endpoints[K]>
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
: {}
|
|
611
|
+
: Plugins extends (infer Plugin)[]
|
|
612
|
+
? Plugin extends { endpoints: infer Endpoints extends Record<string, unknown> }
|
|
613
|
+
? {
|
|
614
|
+
[K in keyof Endpoints as _RoutePathFromEndpoint<Endpoints[K]>]: {
|
|
615
|
+
[M in _RouteMethodFromEndpoint<Endpoints[K]> | 'default']: M extends 'default' ? _RouteDefaultResponse<Endpoints[K]> : _RouteResponseFromEndpoint<Endpoints[K]>
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
: {}
|
|
619
|
+
: {}
|
|
620
|
+
type _PluginAuthInternalApi = _UnionToIntersection<_PluginEndpointMaps<_RawPlugins>>
|
|
621
|
+
type _GeneratedAuthInternalApi = _CoreAuthInternalApi & _PluginAuthInternalApi
|
|
622
|
+
|
|
623
|
+
type _RoutePathToRequestPath<Path extends string> = Path extends \`\${infer Prefix}:\${string}/\${infer Rest}\`
|
|
624
|
+
? \`\${Prefix}\${string}/\${_RoutePathToRequestPath<Rest>}\`
|
|
625
|
+
: Path extends \`\${infer Prefix}:\${string}\`
|
|
626
|
+
? \`\${Prefix}\${string}\`
|
|
627
|
+
: Path
|
|
628
|
+
type _AuthApiPatternPath = Extract<keyof _GeneratedAuthInternalApi, string>
|
|
629
|
+
type _AuthApiRequestPath = _RoutePathToRequestPath<_AuthApiPatternPath>
|
|
630
|
+
type _AuthPatternFromRequestPath<Path extends string> = {
|
|
631
|
+
[Pattern in _AuthApiPatternPath]: Path extends _RoutePathToRequestPath<Pattern> ? Pattern : never
|
|
632
|
+
}[_AuthApiPatternPath]
|
|
633
|
+
type _AuthEndpointMethod<Path extends _AuthApiRequestPath> = Extract<keyof _GeneratedAuthInternalApi[_AuthPatternFromRequestPath<Path>], string>
|
|
634
|
+
|
|
635
|
+
type _AuthFetchMethod<Path extends _AuthApiRequestPath> = Extract<Exclude<import('nitropack/types').NitroFetchOptions<Path>['method'], undefined>, string>
|
|
636
|
+
type _AuthFetchDefaultMethod<Path extends _AuthApiRequestPath> = 'get'
|
|
637
|
+
type _AuthFetchResolvedMethod<Path extends _AuthApiRequestPath, Method extends string> = Lowercase<Method> extends _AuthEndpointMethod<Path>
|
|
638
|
+
? Lowercase<Method>
|
|
639
|
+
: never
|
|
640
|
+
type _AuthFetchResult<Path extends _AuthApiRequestPath, Method extends string> = _GeneratedAuthInternalApi[_AuthPatternFromRequestPath<Path>][_AuthFetchResolvedMethod<Path, Method>]
|
|
641
|
+
|
|
642
|
+
declare module '#nuxt-better-auth' {
|
|
643
|
+
export type AuthApiInternalRoutes = _GeneratedAuthInternalApi
|
|
644
|
+
export type AuthApiEndpointPatternPath = _AuthApiPatternPath
|
|
645
|
+
export type AuthApiEndpointPath = _AuthApiRequestPath
|
|
646
|
+
export type AuthApiEndpointMethod<Path extends AuthApiEndpointPath> = _AuthEndpointMethod<Path>
|
|
647
|
+
export type AuthApiEndpointResponse<
|
|
648
|
+
Path extends AuthApiEndpointPath,
|
|
649
|
+
Method extends AuthApiEndpointMethod<Path> = AuthApiEndpointMethod<Path>,
|
|
650
|
+
> = AuthApiInternalRoutes[_AuthPatternFromRequestPath<Path>][Method]
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
declare module 'nuxt/dist/app/composables/fetch' {
|
|
654
|
+
export function useFetch<
|
|
655
|
+
ErrorT = FetchError,
|
|
656
|
+
Path extends import('#nuxt-better-auth').AuthApiEndpointPath = import('#nuxt-better-auth').AuthApiEndpointPath,
|
|
657
|
+
Method extends _AuthFetchMethod<Path> = _AuthFetchDefaultMethod<Path>,
|
|
658
|
+
_ResT = _AuthFetchResult<Path, Method>,
|
|
659
|
+
DataT = _ResT,
|
|
660
|
+
PickKeys extends import('nuxt/dist/app/composables/asyncData').KeysOf<DataT> = import('nuxt/dist/app/composables/asyncData').KeysOf<DataT>,
|
|
661
|
+
DefaultT = undefined,
|
|
662
|
+
>(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>
|
|
663
|
+
export function useFetch<
|
|
664
|
+
ErrorT = FetchError,
|
|
665
|
+
Path extends import('#nuxt-better-auth').AuthApiEndpointPath = import('#nuxt-better-auth').AuthApiEndpointPath,
|
|
666
|
+
Method extends _AuthFetchMethod<Path> = _AuthFetchDefaultMethod<Path>,
|
|
667
|
+
_ResT = _AuthFetchResult<Path, Method>,
|
|
668
|
+
DataT = _ResT,
|
|
669
|
+
PickKeys extends import('nuxt/dist/app/composables/asyncData').KeysOf<DataT> = import('nuxt/dist/app/composables/asyncData').KeysOf<DataT>,
|
|
670
|
+
DefaultT = DataT,
|
|
671
|
+
>(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>
|
|
672
|
+
|
|
673
|
+
export function useLazyFetch<
|
|
674
|
+
ErrorT = FetchError,
|
|
675
|
+
Path extends import('#nuxt-better-auth').AuthApiEndpointPath = import('#nuxt-better-auth').AuthApiEndpointPath,
|
|
676
|
+
Method extends _AuthFetchMethod<Path> = _AuthFetchDefaultMethod<Path>,
|
|
677
|
+
_ResT = _AuthFetchResult<Path, Method>,
|
|
678
|
+
DataT = _ResT,
|
|
679
|
+
PickKeys extends import('nuxt/dist/app/composables/asyncData').KeysOf<DataT> = import('nuxt/dist/app/composables/asyncData').KeysOf<DataT>,
|
|
680
|
+
DefaultT = undefined,
|
|
681
|
+
>(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>
|
|
682
|
+
export function useLazyFetch<
|
|
683
|
+
ErrorT = FetchError,
|
|
684
|
+
Path extends import('#nuxt-better-auth').AuthApiEndpointPath = import('#nuxt-better-auth').AuthApiEndpointPath,
|
|
685
|
+
Method extends _AuthFetchMethod<Path> = _AuthFetchDefaultMethod<Path>,
|
|
686
|
+
_ResT = _AuthFetchResult<Path, Method>,
|
|
687
|
+
DataT = _ResT,
|
|
688
|
+
PickKeys extends import('nuxt/dist/app/composables/asyncData').KeysOf<DataT> = import('nuxt/dist/app/composables/asyncData').KeysOf<DataT>,
|
|
689
|
+
DefaultT = DataT,
|
|
690
|
+
>(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>
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
declare module 'nuxt/app' {
|
|
694
|
+
export function useFetch<
|
|
695
|
+
ErrorT = FetchError,
|
|
696
|
+
Path extends import('#nuxt-better-auth').AuthApiEndpointPath = import('#nuxt-better-auth').AuthApiEndpointPath,
|
|
697
|
+
Method extends _AuthFetchMethod<Path> = _AuthFetchDefaultMethod<Path>,
|
|
698
|
+
_ResT = _AuthFetchResult<Path, Method>,
|
|
699
|
+
DataT = _ResT,
|
|
700
|
+
PickKeys extends import('nuxt/dist/app/composables/asyncData').KeysOf<DataT> = import('nuxt/dist/app/composables/asyncData').KeysOf<DataT>,
|
|
701
|
+
DefaultT = undefined,
|
|
702
|
+
>(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>
|
|
703
|
+
export function useFetch<
|
|
704
|
+
ErrorT = FetchError,
|
|
705
|
+
Path extends import('#nuxt-better-auth').AuthApiEndpointPath = import('#nuxt-better-auth').AuthApiEndpointPath,
|
|
706
|
+
Method extends _AuthFetchMethod<Path> = _AuthFetchDefaultMethod<Path>,
|
|
707
|
+
_ResT = _AuthFetchResult<Path, Method>,
|
|
708
|
+
DataT = _ResT,
|
|
709
|
+
PickKeys extends import('nuxt/dist/app/composables/asyncData').KeysOf<DataT> = import('nuxt/dist/app/composables/asyncData').KeysOf<DataT>,
|
|
710
|
+
DefaultT = DataT,
|
|
711
|
+
>(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>
|
|
712
|
+
|
|
713
|
+
export function useLazyFetch<
|
|
714
|
+
ErrorT = FetchError,
|
|
715
|
+
Path extends import('#nuxt-better-auth').AuthApiEndpointPath = import('#nuxt-better-auth').AuthApiEndpointPath,
|
|
716
|
+
Method extends _AuthFetchMethod<Path> = _AuthFetchDefaultMethod<Path>,
|
|
717
|
+
_ResT = _AuthFetchResult<Path, Method>,
|
|
718
|
+
DataT = _ResT,
|
|
719
|
+
PickKeys extends import('nuxt/dist/app/composables/asyncData').KeysOf<DataT> = import('nuxt/dist/app/composables/asyncData').KeysOf<DataT>,
|
|
720
|
+
DefaultT = undefined,
|
|
721
|
+
>(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>
|
|
722
|
+
export function useLazyFetch<
|
|
723
|
+
ErrorT = FetchError,
|
|
724
|
+
Path extends import('#nuxt-better-auth').AuthApiEndpointPath = import('#nuxt-better-auth').AuthApiEndpointPath,
|
|
725
|
+
Method extends _AuthFetchMethod<Path> = _AuthFetchDefaultMethod<Path>,
|
|
726
|
+
_ResT = _AuthFetchResult<Path, Method>,
|
|
727
|
+
DataT = _ResT,
|
|
728
|
+
PickKeys extends import('nuxt/dist/app/composables/asyncData').KeysOf<DataT> = import('nuxt/dist/app/composables/asyncData').KeysOf<DataT>,
|
|
729
|
+
DefaultT = DataT,
|
|
730
|
+
>(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>
|
|
731
|
+
}
|
|
732
|
+
|
|
549
733
|
declare module 'nitropack' {
|
|
550
734
|
interface NitroRouteRules {
|
|
551
735
|
auth?: import('${runtimeTypesPath}').AuthMeta
|
|
@@ -553,6 +737,7 @@ declare module 'nitropack' {
|
|
|
553
737
|
interface NitroRouteConfig {
|
|
554
738
|
auth?: import('${runtimeTypesPath}').AuthMeta
|
|
555
739
|
}
|
|
740
|
+
interface InternalApi extends _GeneratedAuthInternalApi {}
|
|
556
741
|
}
|
|
557
742
|
declare module 'nitropack/types' {
|
|
558
743
|
interface NitroRouteRules {
|
|
@@ -561,6 +746,7 @@ declare module 'nitropack/types' {
|
|
|
561
746
|
interface NitroRouteConfig {
|
|
562
747
|
auth?: import('${runtimeTypesPath}').AuthMeta
|
|
563
748
|
}
|
|
749
|
+
interface InternalApi extends _GeneratedAuthInternalApi {}
|
|
564
750
|
}
|
|
565
751
|
export {}
|
|
566
752
|
`
|
|
@@ -572,10 +758,10 @@ function registerSharedTypeTemplates(input) {
|
|
|
572
758
|
getContents: () => `
|
|
573
759
|
import type { AppSession } from '${input.runtimeTypesAugmentPath}'
|
|
574
760
|
export * from '${input.runtimeTypesAugmentPath}'
|
|
575
|
-
export type { AuthMeta, AuthMode, AuthRouteRules, Auth, InferUser, InferSession } from '${input.runtimeTypesPath}'
|
|
761
|
+
export type { AuthMeta, AuthMode, AuthRouteRules, AuthSocialProviderId, Auth, InferUser, InferSession } from '${input.runtimeTypesPath}'
|
|
576
762
|
declare module 'h3' {
|
|
577
763
|
interface H3EventContext {
|
|
578
|
-
|
|
764
|
+
requestSession?: AppSession | null
|
|
579
765
|
}
|
|
580
766
|
}
|
|
581
767
|
`
|
|
@@ -766,6 +952,21 @@ export { schema }
|
|
|
766
952
|
runtimeTypesPath: resolver.resolve("./runtime/types"),
|
|
767
953
|
clientConfigPath
|
|
768
954
|
});
|
|
955
|
+
const runtimeRouteRulesSource = nuxt.options.nitro?.routeRules || nuxt.options.routeRules || {};
|
|
956
|
+
const authRouteRules = Object.fromEntries(
|
|
957
|
+
Object.entries(runtimeRouteRulesSource).flatMap(([path, rule]) => {
|
|
958
|
+
if (!rule || typeof rule !== "object" || !("auth" in rule))
|
|
959
|
+
return [];
|
|
960
|
+
return [[path, { auth: rule.auth }]];
|
|
961
|
+
})
|
|
962
|
+
);
|
|
963
|
+
const authRouteRulesTemplate = addTemplate({
|
|
964
|
+
filename: "better-auth/route-rules.mjs",
|
|
965
|
+
getContents: () => `export const authRouteRules = ${JSON.stringify(authRouteRules, null, 2)}
|
|
966
|
+
`,
|
|
967
|
+
write: true
|
|
968
|
+
});
|
|
969
|
+
nuxt.options.alias["#auth/route-rules"] = authRouteRulesTemplate.dst;
|
|
769
970
|
registerTemplateHmrHook(nuxt);
|
|
770
971
|
registerServerRuntime({ clientOnly, resolve: resolver.resolve });
|
|
771
972
|
registerAuthMiddlewareHook(nuxt, resolver.resolve);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { AsyncDataOptions } from '#app';
|
|
2
|
+
import { useAuthRequestFetch } from './useAuthRequestFetch.js';
|
|
3
|
+
export interface UseAuthAsyncDataOptions<T> extends Omit<AsyncDataOptions<T | null>, 'default'> {
|
|
4
|
+
requireAuth?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare function useAuthAsyncData<T>(key: string, fetcher: (requestFetch: ReturnType<typeof useAuthRequestFetch>) => Promise<T>, options?: UseAuthAsyncDataOptions<T>): any;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { useAsyncData } from "#imports";
|
|
2
|
+
import { useAuthRequestFetch } from "./useAuthRequestFetch.js";
|
|
3
|
+
import { useUserSession } from "./useUserSession.js";
|
|
4
|
+
export function useAuthAsyncData(key, fetcher, options = {}) {
|
|
5
|
+
const requestFetch = useAuthRequestFetch();
|
|
6
|
+
const { loggedIn } = useUserSession();
|
|
7
|
+
const { requireAuth = true, ...asyncDataOptions } = options;
|
|
8
|
+
return useAsyncData(key, async () => {
|
|
9
|
+
if (requireAuth && !loggedIn.value)
|
|
10
|
+
return null;
|
|
11
|
+
return await fetcher(requestFetch);
|
|
12
|
+
}, {
|
|
13
|
+
default: () => null,
|
|
14
|
+
...asyncDataOptions
|
|
15
|
+
});
|
|
16
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { UserAuthActionHandle } from '../internal/auth-action-handles.js';
|
|
2
|
+
import type { UseUserSessionReturn } from './useUserSession.js';
|
|
3
|
+
type AppAuthClient = NonNullable<UseUserSessionReturn['client']>;
|
|
4
|
+
export declare function useAuthClientAction<TArgs extends unknown[], TResult>(select: (client: AppAuthClient) => (...args: TArgs) => Promise<TResult>): UserAuthActionHandle<TArgs, TResult>;
|
|
5
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useUserSession } from "#imports";
|
|
2
|
+
import { useAction } from "./useAction.js";
|
|
3
|
+
export function useAuthClientAction(select) {
|
|
4
|
+
if (typeof select !== "function")
|
|
5
|
+
throw new TypeError("useAuthClientAction(select) requires a selector function");
|
|
6
|
+
return useAction(async (...args) => {
|
|
7
|
+
const { client } = useUserSession();
|
|
8
|
+
if (!client)
|
|
9
|
+
throw new Error("Auth client is unavailable. This action can only run on client-side.");
|
|
10
|
+
const method = select(client);
|
|
11
|
+
if (typeof method !== "function")
|
|
12
|
+
throw new TypeError("useAuthClientAction(select) must resolve to a function");
|
|
13
|
+
return method(...args);
|
|
14
|
+
});
|
|
15
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AuthApiEndpointMethod, AuthApiEndpointPath, AuthApiEndpointResponse } from '#nuxt-better-auth';
|
|
2
|
+
import type { NitroFetchOptions } from 'nitropack/types';
|
|
3
|
+
import { useRequestFetch } from '#imports';
|
|
4
|
+
type AuthRequestFetchExtractedMethod<Options> = Options extends undefined ? 'get' : Lowercase<Extract<Exclude<Options extends {
|
|
5
|
+
method?: infer Method;
|
|
6
|
+
} ? Method : never, undefined>, string>> extends infer NormalizedMethod extends string ? NormalizedMethod : 'get';
|
|
7
|
+
type AuthRequestFetchMethodFromOptions<Path extends AuthApiEndpointPath, Options> = NitroFetchOptions<Path> extends Options ? 'get' : AuthRequestFetchExtractedMethod<Options>;
|
|
8
|
+
type AuthRequestFetchResolvedMethod<Path extends AuthApiEndpointPath, Options> = Extract<AuthRequestFetchMethodFromOptions<Path, Options>, AuthApiEndpointMethod<Path>> extends infer Method extends string ? Method : never;
|
|
9
|
+
type AuthRequestFetch = <Path extends AuthApiEndpointPath, Options extends NitroFetchOptions<Path> = NitroFetchOptions<Path>>(request: Path, opts?: Options) => Promise<AuthApiEndpointResponse<Path, Extract<AuthRequestFetchResolvedMethod<Path, Options>, AuthApiEndpointMethod<Path>>>>;
|
|
10
|
+
export declare function useAuthRequestFetch(): AuthRequestFetch & ReturnType<typeof useRequestFetch>;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AppAuthClient, AuthSocialProviderRegistry } from '#nuxt-better-auth';
|
|
2
|
+
import type { ActionHandleFor } from '../internal/auth-action-handles.js';
|
|
3
|
+
type SignIn = NonNullable<AppAuthClient>['signIn'];
|
|
4
|
+
type AuthSocialProviderId = AuthSocialProviderRegistry extends {
|
|
5
|
+
ids: infer T;
|
|
6
|
+
} ? Extract<T, string> : never;
|
|
7
|
+
type TypedSocialMethod<Method> = Method extends (data: infer Data, ...rest: infer Rest) => Promise<infer Result> ? (data: Omit<Extract<Data, Record<string, unknown>>, 'provider'> & {
|
|
8
|
+
provider: AuthSocialProviderId;
|
|
9
|
+
}, ...rest: Rest) => Promise<Result> : Method;
|
|
10
|
+
type SignInWithTypedSocial = Omit<SignIn, 'social'> & (SignIn extends {
|
|
11
|
+
social: infer SocialMethod;
|
|
12
|
+
} ? {
|
|
13
|
+
social: TypedSocialMethod<SocialMethod>;
|
|
14
|
+
} : unknown);
|
|
15
|
+
export declare function useSignIn<MethodKey extends keyof SignInWithTypedSocial>(method: MethodKey): ActionHandleFor<SignInWithTypedSocial[MethodKey]>;
|
|
16
|
+
export {};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useUserSession } from "#imports";
|
|
2
2
|
import { createActionHandles } from "../internal/auth-action-handles.js";
|
|
3
|
-
export function
|
|
3
|
+
export function useSignIn(method) {
|
|
4
4
|
if (method === void 0 || method === null)
|
|
5
|
-
throw new TypeError("
|
|
5
|
+
throw new TypeError("useSignIn(method) requires a sign-in method key");
|
|
6
6
|
const handles = createActionHandles(() => useUserSession().signIn, "signIn");
|
|
7
7
|
return handles[method];
|
|
8
8
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AppAuthClient } from '#nuxt-better-auth';
|
|
2
2
|
import type { ActionHandleFor } from '../internal/auth-action-handles.js';
|
|
3
3
|
type SignUp = NonNullable<AppAuthClient>['signUp'];
|
|
4
|
-
export declare function
|
|
4
|
+
export declare function useSignUp<MethodKey extends keyof SignUp>(method: MethodKey): ActionHandleFor<SignUp[MethodKey]>;
|
|
5
5
|
export {};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useUserSession } from "#imports";
|
|
2
2
|
import { createActionHandles } from "../internal/auth-action-handles.js";
|
|
3
|
-
export function
|
|
3
|
+
export function useSignUp(method) {
|
|
4
4
|
if (method === void 0 || method === null)
|
|
5
|
-
throw new TypeError("
|
|
5
|
+
throw new TypeError("useSignUp(method) requires a sign-up method key");
|
|
6
6
|
const handles = createActionHandles(() => useUserSession().signUp, "signUp");
|
|
7
7
|
return handles[method];
|
|
8
8
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import createAppAuthClient from "#auth/client";
|
|
2
|
-
import { computed, navigateTo, nextTick, useNuxtApp, useRequestHeaders, useRequestURL, useRuntimeConfig, useState, watch } from "#imports";
|
|
2
|
+
import { computed, navigateTo, nextTick, useNuxtApp, useRequestFetch, useRequestHeaders, useRequestURL, useRuntimeConfig, useState, watch } from "#imports";
|
|
3
3
|
import { normalizeAuthActionError } from "../internal/auth-action-error.js";
|
|
4
4
|
let _sessionSignalListenerBound = false;
|
|
5
5
|
let _client = null;
|
|
@@ -39,13 +39,23 @@ export function useUserSession() {
|
|
|
39
39
|
const runtimeFlags = getRuntimeFlags();
|
|
40
40
|
const runtimeConfig = useRuntimeConfig();
|
|
41
41
|
const requestURL = useRequestURL();
|
|
42
|
+
const nuxtApp = useNuxtApp();
|
|
42
43
|
const client = runtimeFlags.client ? getClient(runtimeConfig.public.siteUrl || requestURL.origin) : null;
|
|
43
44
|
const session = useState("auth:session", () => null);
|
|
44
45
|
const user = useState("auth:user", () => null);
|
|
45
46
|
const authReady = useState("auth:ready", () => false);
|
|
47
|
+
const prerenderReadyResetQueued = useState("auth:prerender-ready-reset-queued", () => false);
|
|
48
|
+
const hydrationReconcileQueued = useState("auth:hydration-reconcile-queued", () => false);
|
|
46
49
|
const ready = computed(() => authReady.value);
|
|
47
50
|
const loggedIn = computed(() => Boolean(session.value && user.value));
|
|
48
|
-
const
|
|
51
|
+
const isPrerenderedPayload = computed(() => Boolean(nuxtApp.payload.prerenderedAt || nuxtApp.payload.isCached));
|
|
52
|
+
const isPrerenderHydrationEmptySnapshot = computed(() => {
|
|
53
|
+
if (!runtimeFlags.client)
|
|
54
|
+
return false;
|
|
55
|
+
if (!nuxtApp.isHydrating || !nuxtApp.payload.serverRendered || !isPrerenderedPayload.value)
|
|
56
|
+
return false;
|
|
57
|
+
return !session.value && !user.value;
|
|
58
|
+
});
|
|
49
59
|
const skipHydratedSsrGetSession = computed(() => {
|
|
50
60
|
const authConfig = runtimeConfig.public.auth;
|
|
51
61
|
return Boolean(authConfig?.session?.skipHydratedSsrGetSession);
|
|
@@ -57,10 +67,21 @@ export function useUserSession() {
|
|
|
57
67
|
return false;
|
|
58
68
|
if (!nuxtApp.payload.serverRendered)
|
|
59
69
|
return false;
|
|
60
|
-
if (
|
|
70
|
+
if (isPrerenderedPayload.value)
|
|
61
71
|
return false;
|
|
62
72
|
return Boolean(session.value && user.value);
|
|
63
73
|
});
|
|
74
|
+
if (isPrerenderHydrationEmptySnapshot.value && authReady.value && !prerenderReadyResetQueued.value) {
|
|
75
|
+
prerenderReadyResetQueued.value = true;
|
|
76
|
+
nuxtApp.hook("app:suspense:resolve", () => {
|
|
77
|
+
try {
|
|
78
|
+
if (!session.value && !user.value && authReady.value)
|
|
79
|
+
authReady.value = false;
|
|
80
|
+
} finally {
|
|
81
|
+
prerenderReadyResetQueued.value = false;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
64
85
|
if (shouldSkipInitialClientSessionFetch.value && !authReady.value)
|
|
65
86
|
authReady.value = true;
|
|
66
87
|
function clearSession() {
|
|
@@ -97,14 +118,28 @@ export function useUserSession() {
|
|
|
97
118
|
watch(
|
|
98
119
|
() => clientSession.value,
|
|
99
120
|
(newSession) => {
|
|
121
|
+
const shouldWaitForPrerenderResolution = isPrerenderHydrationEmptySnapshot.value && !newSession?.data?.session && !newSession?.data?.user;
|
|
122
|
+
if (shouldWaitForPrerenderResolution)
|
|
123
|
+
return;
|
|
100
124
|
if (newSession?.data?.session && newSession?.data?.user) {
|
|
101
125
|
const { token: _, ...safeSession } = newSession.data.session;
|
|
102
126
|
session.value = safeSession;
|
|
103
127
|
user.value = newSession.data.user;
|
|
104
|
-
} else if (!newSession?.isPending) {
|
|
128
|
+
} else if (!newSession?.isPending && !newSession?.isRefetching) {
|
|
129
|
+
const isHydrationEmptySnapshot = nuxtApp.isHydrating && nuxtApp.payload.serverRendered && Boolean(session.value && user.value) && !newSession?.data?.session && !newSession?.data?.user;
|
|
130
|
+
if (isHydrationEmptySnapshot) {
|
|
131
|
+
if (!hydrationReconcileQueued.value) {
|
|
132
|
+
hydrationReconcileQueued.value = true;
|
|
133
|
+
nuxtApp.hook("app:mounted", async () => {
|
|
134
|
+
await fetchSession({ force: true });
|
|
135
|
+
hydrationReconcileQueued.value = false;
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
105
140
|
clearSession();
|
|
106
141
|
}
|
|
107
|
-
if (!authReady.value && !newSession?.isPending)
|
|
142
|
+
if (!authReady.value && !newSession?.isPending && !newSession?.isRefetching)
|
|
108
143
|
authReady.value = true;
|
|
109
144
|
},
|
|
110
145
|
{ immediate: true, deep: true }
|
|
@@ -152,6 +187,19 @@ export function useUserSession() {
|
|
|
152
187
|
await navigateTo(target);
|
|
153
188
|
};
|
|
154
189
|
}
|
|
190
|
+
function withFallbackSocialCallbackURL(data) {
|
|
191
|
+
const callbackURL = resolvePostAuthRedirect();
|
|
192
|
+
if (!callbackURL)
|
|
193
|
+
return data;
|
|
194
|
+
if (!isRecord(data))
|
|
195
|
+
return { callbackURL };
|
|
196
|
+
if (typeof data.callbackURL === "string")
|
|
197
|
+
return data;
|
|
198
|
+
return {
|
|
199
|
+
...data,
|
|
200
|
+
callbackURL
|
|
201
|
+
};
|
|
202
|
+
}
|
|
155
203
|
function wrapOnSuccess(cb) {
|
|
156
204
|
return async (ctx) => {
|
|
157
205
|
await fetchSession({ force: true });
|
|
@@ -161,12 +209,15 @@ export function useUserSession() {
|
|
|
161
209
|
await cb(ctx);
|
|
162
210
|
};
|
|
163
211
|
}
|
|
164
|
-
function wrapAuthMethod(method) {
|
|
212
|
+
function wrapAuthMethod(method, wrapOptions = {}) {
|
|
165
213
|
return (async (...args) => {
|
|
166
|
-
const
|
|
214
|
+
const originalData = args[0];
|
|
167
215
|
const options = args[1];
|
|
216
|
+
const data = wrapOptions.transformData?.(originalData, options) ?? originalData;
|
|
168
217
|
const dataRecord = isRecord(data) ? data : void 0;
|
|
169
218
|
const optionsRecord = isRecord(options) ? options : void 0;
|
|
219
|
+
if (wrapOptions.shouldSkipSessionSync?.(data, options))
|
|
220
|
+
return method(data, options);
|
|
170
221
|
const fetchOptions = isRecord(dataRecord?.fetchOptions) ? dataRecord.fetchOptions : void 0;
|
|
171
222
|
const nestedOnSuccess = fetchOptions?.onSuccess;
|
|
172
223
|
const topLevelOnSuccess = optionsRecord?.onSuccess;
|
|
@@ -219,7 +270,15 @@ export function useUserSession() {
|
|
|
219
270
|
const method = targetRecord[prop];
|
|
220
271
|
if (typeof method !== "function")
|
|
221
272
|
return method;
|
|
222
|
-
|
|
273
|
+
const shouldSkipSessionSync = prop === "social" ? (data) => {
|
|
274
|
+
const socialData = isRecord(data) ? data : void 0;
|
|
275
|
+
return socialData?.disableRedirect !== true;
|
|
276
|
+
} : void 0;
|
|
277
|
+
const transformData = prop === "social" ? withFallbackSocialCallbackURL : void 0;
|
|
278
|
+
return wrapAuthMethod(
|
|
279
|
+
(...args) => targetRecord[prop](...args),
|
|
280
|
+
{ shouldSkipSessionSync, transformData }
|
|
281
|
+
);
|
|
223
282
|
}
|
|
224
283
|
}) : new Proxy({}, {
|
|
225
284
|
get: (_, prop) => {
|
|
@@ -241,8 +300,23 @@ export function useUserSession() {
|
|
|
241
300
|
});
|
|
242
301
|
async function fetchSession(options = {}) {
|
|
243
302
|
if (runtimeFlags.server) {
|
|
244
|
-
|
|
245
|
-
|
|
303
|
+
try {
|
|
304
|
+
const headers = options.headers || useRequestHeaders(["cookie"]);
|
|
305
|
+
const requestFetch = useRequestFetch();
|
|
306
|
+
const data = await requestFetch("/api/auth/get-session", { headers });
|
|
307
|
+
if (data?.session && data?.user) {
|
|
308
|
+
const { token: _, ...safeSession } = data.session;
|
|
309
|
+
session.value = safeSession;
|
|
310
|
+
user.value = data.user;
|
|
311
|
+
} else {
|
|
312
|
+
clearSession();
|
|
313
|
+
}
|
|
314
|
+
} catch {
|
|
315
|
+
clearSession();
|
|
316
|
+
} finally {
|
|
317
|
+
if (!authReady.value)
|
|
318
|
+
authReady.value = true;
|
|
319
|
+
}
|
|
246
320
|
return;
|
|
247
321
|
}
|
|
248
322
|
if (client) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export const DEFAULT_AUTH_ACTION_ERROR_MESSAGE = "Request failed. Please try again.";
|
|
1
2
|
function isRecord(value) {
|
|
2
3
|
return Boolean(value && typeof value === "object");
|
|
3
4
|
}
|
|
@@ -8,7 +9,7 @@ function getMessage(value) {
|
|
|
8
9
|
return value;
|
|
9
10
|
if (isRecord(value) && typeof value.message === "string")
|
|
10
11
|
return value.message;
|
|
11
|
-
return
|
|
12
|
+
return DEFAULT_AUTH_ACTION_ERROR_MESSAGE;
|
|
12
13
|
}
|
|
13
14
|
function getCode(value) {
|
|
14
15
|
if (!isRecord(value))
|
|
@@ -7,8 +7,12 @@ export interface UserAuthActionHandle<TArgs extends unknown[], TResult> {
|
|
|
7
7
|
data: Ref<TResult | null>;
|
|
8
8
|
error: Ref<AuthActionError | null>;
|
|
9
9
|
}
|
|
10
|
+
export interface CreateActionHandleOptions {
|
|
11
|
+
keepPendingOnRedirect?: boolean;
|
|
12
|
+
}
|
|
10
13
|
export type ActionHandleFor<T> = T extends (...args: infer A) => Promise<infer R> ? UserAuthActionHandle<A, R> : never;
|
|
11
14
|
export type ActionHandleMap<T> = {
|
|
12
15
|
[K in keyof T]: ActionHandleFor<T[K]>;
|
|
13
16
|
};
|
|
17
|
+
export declare function createActionHandle<TArgs extends unknown[], TResult>(getMethod: () => (...args: TArgs) => Promise<TResult>, options?: CreateActionHandleOptions): UserAuthActionHandle<TArgs, TResult>;
|
|
14
18
|
export declare function createActionHandles<T extends object>(getTarget: () => T, targetName: string): ActionHandleMap<T>;
|
|
@@ -10,7 +10,23 @@ function isErrorResult(value) {
|
|
|
10
10
|
return false;
|
|
11
11
|
return Boolean(value.error);
|
|
12
12
|
}
|
|
13
|
-
function
|
|
13
|
+
function isRedirectResult(value) {
|
|
14
|
+
if (!isRecord(value))
|
|
15
|
+
return false;
|
|
16
|
+
return value.redirect === true && typeof value.url === "string" && value.url.length > 0;
|
|
17
|
+
}
|
|
18
|
+
function getRedirectResult(value) {
|
|
19
|
+
if (isRedirectResult(value))
|
|
20
|
+
return value;
|
|
21
|
+
if (!isRecord(value))
|
|
22
|
+
return null;
|
|
23
|
+
const nested = value.data;
|
|
24
|
+
if (isRedirectResult(nested))
|
|
25
|
+
return nested;
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
const REDIRECT_PENDING_FALLBACK_MS = 1e4;
|
|
29
|
+
export function createActionHandle(getMethod, options = {}) {
|
|
14
30
|
const status = ref("idle");
|
|
15
31
|
const data = ref(null);
|
|
16
32
|
const error = ref(null);
|
|
@@ -32,6 +48,20 @@ function createActionHandle(getMethod) {
|
|
|
32
48
|
return;
|
|
33
49
|
}
|
|
34
50
|
if (callId === latestCallId) {
|
|
51
|
+
if (options.keepPendingOnRedirect !== false) {
|
|
52
|
+
const redirectResult = getRedirectResult(result);
|
|
53
|
+
if (redirectResult) {
|
|
54
|
+
status.value = "pending";
|
|
55
|
+
data.value = result;
|
|
56
|
+
error.value = null;
|
|
57
|
+
setTimeout(() => {
|
|
58
|
+
if (callId !== latestCallId || status.value !== "pending")
|
|
59
|
+
return;
|
|
60
|
+
status.value = "success";
|
|
61
|
+
}, REDIRECT_PENDING_FALLBACK_MS);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
35
65
|
status.value = "success";
|
|
36
66
|
data.value = result;
|
|
37
67
|
error.value = null;
|
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
import { createError, defineNuxtRouteMiddleware, getRouteRules, navigateTo, useNuxtApp, useRequestHeaders, useRuntimeConfig, useUserSession } from "#imports";
|
|
2
|
+
import { defu } from "defu";
|
|
3
|
+
import { createRouter, toRouteMatcher } from "radix3";
|
|
2
4
|
import { matchesUser } from "../../utils/match-user.js";
|
|
5
|
+
let authRouteRulesPromise = null;
|
|
6
|
+
let routeRulesMatcherPromise = null;
|
|
3
7
|
export default defineNuxtRouteMiddleware(async (to) => {
|
|
4
8
|
const nuxtApp = useNuxtApp();
|
|
5
|
-
if (import.meta.client) {
|
|
6
|
-
const isPrerendered = nuxtApp.payload.prerenderedAt || nuxtApp.payload.isCached;
|
|
7
|
-
if (isPrerendered && nuxtApp.isHydrating)
|
|
8
|
-
return;
|
|
9
|
-
}
|
|
10
9
|
if (to.meta.auth === void 0) {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
const routeRulesMatcher = await getRouteRulesMatcher();
|
|
11
|
+
const matches = routeRulesMatcher?.matchAll(to.path);
|
|
12
|
+
if (matches?.length) {
|
|
13
|
+
const merged = defu({}, ...matches.reverse());
|
|
14
|
+
if (merged.auth !== void 0)
|
|
15
|
+
to.meta.auth = merged.auth;
|
|
16
|
+
}
|
|
17
|
+
if (to.meta.auth === void 0) {
|
|
18
|
+
const rules = await getRouteRules({ path: to.path });
|
|
19
|
+
if (rules.auth !== void 0)
|
|
20
|
+
to.meta.auth = rules.auth;
|
|
21
|
+
}
|
|
14
22
|
}
|
|
15
23
|
const auth = to.meta.auth;
|
|
16
24
|
if (auth === void 0 || auth === false)
|
|
@@ -19,7 +27,8 @@ export default defineNuxtRouteMiddleware(async (to) => {
|
|
|
19
27
|
const { fetchSession, user, loggedIn } = useUserSession();
|
|
20
28
|
if (!loggedIn.value) {
|
|
21
29
|
const headers = import.meta.server ? useRequestHeaders(["cookie"]) : void 0;
|
|
22
|
-
|
|
30
|
+
const isHydratedPrerenderPayload = (import.meta.client || !import.meta.server) && nuxtApp.isHydrating && Boolean(nuxtApp.payload.prerenderedAt || nuxtApp.payload.isCached);
|
|
31
|
+
await fetchSession({ headers, ...isHydratedPrerenderPayload ? { force: true } : {} });
|
|
23
32
|
}
|
|
24
33
|
const mode = typeof auth === "string" ? auth : auth?.only ?? "user";
|
|
25
34
|
const redirectTo = typeof auth === "object" ? auth.redirectTo : void 0;
|
|
@@ -71,3 +80,19 @@ function resolveLoginRedirect(input) {
|
|
|
71
80
|
queryObj[redirectQueryKey] = route.fullPath;
|
|
72
81
|
return { to: { path, query: queryObj, ...hash ? { hash: `#${hash}` } : {} }, external: false };
|
|
73
82
|
}
|
|
83
|
+
async function getAuthRouteRules() {
|
|
84
|
+
if (!authRouteRulesPromise) {
|
|
85
|
+
authRouteRulesPromise = import("#auth/route-rules").then((mod) => mod.authRouteRules || {}).catch(() => ({}));
|
|
86
|
+
}
|
|
87
|
+
return await authRouteRulesPromise;
|
|
88
|
+
}
|
|
89
|
+
async function getRouteRulesMatcher() {
|
|
90
|
+
if (!routeRulesMatcherPromise) {
|
|
91
|
+
routeRulesMatcherPromise = getAuthRouteRules().then((authRouteRules) => {
|
|
92
|
+
if (!Object.keys(authRouteRules).length)
|
|
93
|
+
return null;
|
|
94
|
+
return toRouteMatcher(createRouter({ routes: authRouteRules }));
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return await routeRulesMatcherPromise;
|
|
98
|
+
}
|
|
@@ -14,22 +14,22 @@ declare const _default: import("h3").EventHandler<import("h3").EventHandlerReque
|
|
|
14
14
|
databaseProvider: "none" | "nuxthub";
|
|
15
15
|
};
|
|
16
16
|
server: {
|
|
17
|
-
baseURL:
|
|
18
|
-
basePath:
|
|
17
|
+
baseURL: any;
|
|
18
|
+
basePath: any;
|
|
19
19
|
socialProviders: string[];
|
|
20
|
-
plugins:
|
|
21
|
-
trustedOrigins:
|
|
22
|
-
configuredTrustedOrigins:
|
|
20
|
+
plugins: any;
|
|
21
|
+
trustedOrigins: any;
|
|
22
|
+
configuredTrustedOrigins: any;
|
|
23
23
|
session: {
|
|
24
24
|
expiresIn: string;
|
|
25
25
|
updateAge: string;
|
|
26
|
-
cookieCache:
|
|
26
|
+
cookieCache: any;
|
|
27
27
|
};
|
|
28
28
|
emailAndPassword: boolean;
|
|
29
|
-
rateLimit:
|
|
29
|
+
rateLimit: any;
|
|
30
30
|
advanced: {
|
|
31
|
-
useSecureCookies:
|
|
32
|
-
disableCSRFCheck:
|
|
31
|
+
useSecureCookies: any;
|
|
32
|
+
disableCSRFCheck: any;
|
|
33
33
|
};
|
|
34
34
|
};
|
|
35
35
|
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { H3Event } from 'h3';
|
|
2
|
+
import createServerAuth from '#auth/server';
|
|
2
3
|
import { betterAuth } from 'better-auth';
|
|
3
|
-
type
|
|
4
|
+
type AuthOptions = ReturnType<typeof createServerAuth>;
|
|
5
|
+
type AuthInstance = ReturnType<typeof betterAuth<AuthOptions>>;
|
|
4
6
|
/** Returns Better Auth instance. Caches per resolved host (or single instance when siteUrl is explicit). */
|
|
5
7
|
export declare function serverAuth(event?: H3Event): AuthInstance;
|
|
6
8
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AppSession, RequireSessionOptions } from '#nuxt-better-auth';
|
|
2
2
|
import type { H3Event } from 'h3';
|
|
3
|
-
export declare function
|
|
3
|
+
export declare function getRequestSession(event: H3Event): Promise<AppSession | null>;
|
|
4
4
|
export declare function getUserSession(event: H3Event): Promise<AppSession | null>;
|
|
5
5
|
export declare function requireUserSession(event: H3Event, options?: RequireSessionOptions): Promise<AppSession>;
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { createError } from "h3";
|
|
2
2
|
import { matchesUser } from "../../utils/match-user.js";
|
|
3
3
|
import { serverAuth } from "./auth.js";
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
function
|
|
4
|
+
const requestSessionLoadKey = Symbol.for("nuxt-better-auth.requestSessionLoad");
|
|
5
|
+
const fallbackRequestSessionContext = /* @__PURE__ */ new WeakMap();
|
|
6
|
+
function getRequestSessionContext(event) {
|
|
7
7
|
const eventWithContext = event;
|
|
8
8
|
if (eventWithContext.context && typeof eventWithContext.context === "object")
|
|
9
9
|
return eventWithContext.context;
|
|
10
|
-
let context =
|
|
10
|
+
let context = fallbackRequestSessionContext.get(event);
|
|
11
11
|
if (!context) {
|
|
12
12
|
context = {};
|
|
13
|
-
|
|
13
|
+
fallbackRequestSessionContext.set(event, context);
|
|
14
14
|
}
|
|
15
15
|
return context;
|
|
16
16
|
}
|
|
@@ -18,34 +18,34 @@ function loadSession(event) {
|
|
|
18
18
|
const auth = serverAuth(event);
|
|
19
19
|
return auth.api.getSession({ headers: event.headers });
|
|
20
20
|
}
|
|
21
|
-
export async function
|
|
22
|
-
const context =
|
|
23
|
-
if (context.
|
|
24
|
-
return context.
|
|
25
|
-
const inFlight = context[
|
|
21
|
+
export async function getRequestSession(event) {
|
|
22
|
+
const context = getRequestSessionContext(event);
|
|
23
|
+
if (context.requestSession !== void 0)
|
|
24
|
+
return context.requestSession;
|
|
25
|
+
const inFlight = context[requestSessionLoadKey];
|
|
26
26
|
if (inFlight)
|
|
27
27
|
return inFlight;
|
|
28
28
|
const load = loadSession(event);
|
|
29
|
-
context[
|
|
29
|
+
context[requestSessionLoadKey] = load;
|
|
30
30
|
try {
|
|
31
31
|
const session = await load;
|
|
32
|
-
context.
|
|
32
|
+
context.requestSession = session;
|
|
33
33
|
return session;
|
|
34
34
|
} finally {
|
|
35
|
-
delete context[
|
|
35
|
+
delete context[requestSessionLoadKey];
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
export async function getUserSession(event) {
|
|
39
|
-
const context =
|
|
40
|
-
if (context.
|
|
41
|
-
return context.
|
|
42
|
-
const inFlight = context[
|
|
39
|
+
const context = getRequestSessionContext(event);
|
|
40
|
+
if (context.requestSession !== void 0)
|
|
41
|
+
return context.requestSession;
|
|
42
|
+
const inFlight = context[requestSessionLoadKey];
|
|
43
43
|
if (inFlight)
|
|
44
44
|
return inFlight;
|
|
45
45
|
return loadSession(event);
|
|
46
46
|
}
|
|
47
47
|
export async function requireUserSession(event, options) {
|
|
48
|
-
const session = await
|
|
48
|
+
const session = await getRequestSession(event);
|
|
49
49
|
if (!session)
|
|
50
50
|
throw createError({ statusCode: 401, statusMessage: "Authentication required" });
|
|
51
51
|
if (options?.user) {
|
package/dist/runtime/types.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import type { AuthUser, UserMatch } from '#nuxt-better-auth';
|
|
1
|
+
import type { AuthSocialProviderRegistry, AuthUser, UserMatch } from '#nuxt-better-auth';
|
|
2
2
|
import type { NitroRouteRules } from 'nitropack/types';
|
|
3
|
-
export type { AppSession, AuthSession, AuthUser, RequireSessionOptions, ServerAuthContext, UserMatch, UserSessionComposable } from './types/augment.js';
|
|
3
|
+
export type { AppSession, AuthSession, AuthSocialProviderRegistry, AuthUser, RequireSessionOptions, ServerAuthContext, UserMatch, UserSessionComposable } from './types/augment.js';
|
|
4
|
+
export type AuthSocialProviderId = AuthSocialProviderRegistry extends {
|
|
5
|
+
ids: infer T;
|
|
6
|
+
} ? Extract<T, string> : never;
|
|
4
7
|
export type { Auth, InferPluginTypes, InferSessionFromClient as InferSession, InferUserFromClient as InferUser } from 'better-auth';
|
|
5
8
|
export interface AuthActionError {
|
|
6
9
|
message: string;
|
package/dist/types.d.mts
CHANGED
|
@@ -6,6 +6,6 @@ export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<
|
|
|
6
6
|
|
|
7
7
|
export { type BetterAuthModuleOptions, type defineClientAuth, type defineServerAuth } from '../dist/runtime/config.js'
|
|
8
8
|
|
|
9
|
-
export { type AppSession, type Auth, type AuthActionError, type AuthMeta, type AuthMode, type AuthRouteRules, type AuthSession, type AuthUser, type InferSession, type InferUser, type RequireSessionOptions, type ServerAuthContext, type UserMatch } from '../dist/runtime/types.js'
|
|
9
|
+
export { type AppSession, type Auth, type AuthActionError, type AuthMeta, type AuthMode, type AuthRouteRules, type AuthSession, type AuthSocialProviderId, type AuthUser, type InferSession, type InferUser, type RequireSessionOptions, type ServerAuthContext, type UserMatch } from '../dist/runtime/types.js'
|
|
10
10
|
|
|
11
11
|
export { default } from './module.mjs'
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onmax/nuxt-better-auth",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.2-alpha.
|
|
4
|
+
"version": "0.0.2-alpha.30",
|
|
5
5
|
"packageManager": "pnpm@10.15.1",
|
|
6
6
|
"description": "Nuxt module for Better Auth integration with NuxtHub, route protection, session management, and role-based access",
|
|
7
7
|
"author": "onmax",
|
|
@@ -70,56 +70,42 @@
|
|
|
70
70
|
}
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
|
-
"@better-auth/cli": "
|
|
74
|
-
"@nuxt/kit": "^4.
|
|
75
|
-
"@nuxt/ui": "^4.
|
|
73
|
+
"@better-auth/cli": "1.5.0-beta.13",
|
|
74
|
+
"@nuxt/kit": "^4.3.1",
|
|
75
|
+
"@nuxt/ui": "^4.5.0",
|
|
76
76
|
"defu": "^6.1.4",
|
|
77
|
-
"jiti": "^2.
|
|
77
|
+
"jiti": "^2.6.1",
|
|
78
78
|
"pathe": "^2.0.3",
|
|
79
79
|
"radix3": "^1.1.2",
|
|
80
80
|
"std-env": "^3.10.0"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
|
-
"@antfu/eslint-config": "^
|
|
84
|
-
"@libsql/client": "^0.
|
|
85
|
-
"@
|
|
86
|
-
"@nuxt/devtools
|
|
83
|
+
"@antfu/eslint-config": "^7.6.1",
|
|
84
|
+
"@libsql/client": "^0.17.0",
|
|
85
|
+
"@libsql/linux-x64-gnu": "0.5.22",
|
|
86
|
+
"@nuxt/devtools": "^3.2.2",
|
|
87
|
+
"@nuxt/devtools-kit": "^3.2.2",
|
|
87
88
|
"@nuxt/module-builder": "^1.0.2",
|
|
88
|
-
"@nuxt/schema": "^4.
|
|
89
|
-
"@nuxt/test-utils": "^
|
|
90
|
-
"@nuxthub/core": "^0.10.
|
|
89
|
+
"@nuxt/schema": "^4.3.1",
|
|
90
|
+
"@nuxt/test-utils": "^4.0.0",
|
|
91
|
+
"@nuxthub/core": "^0.10.6",
|
|
91
92
|
"@types/better-sqlite3": "^7.6.13",
|
|
92
93
|
"@types/node": "latest",
|
|
93
|
-
"better-auth": "
|
|
94
|
-
"better-sqlite3": "^
|
|
95
|
-
"bumpp": "^10.
|
|
94
|
+
"better-auth": "1.5.0",
|
|
95
|
+
"better-sqlite3": "^12.6.2",
|
|
96
|
+
"bumpp": "^10.4.1",
|
|
96
97
|
"changelogen": "^0.6.2",
|
|
97
98
|
"consola": "^3.4.2",
|
|
98
|
-
"drizzle-kit": "^0.31.
|
|
99
|
-
"drizzle-orm": "^0.
|
|
100
|
-
"eslint": "^
|
|
99
|
+
"drizzle-kit": "^0.31.9",
|
|
100
|
+
"drizzle-orm": "^0.45.1",
|
|
101
|
+
"eslint": "^10.0.2",
|
|
101
102
|
"npm-agentskills": "https://pkg.pr.new/onmax/npm-agentskills@394499e",
|
|
102
|
-
"nuxt": "^4.
|
|
103
|
+
"nuxt": "^4.3.1",
|
|
103
104
|
"tinyexec": "^1.0.2",
|
|
104
105
|
"typescript": "~5.9.3",
|
|
105
|
-
"vitest": "^4.0.
|
|
106
|
-
"vitest-package-exports": "^
|
|
107
|
-
"vue-tsc": "^3.
|
|
106
|
+
"vitest": "^4.0.18",
|
|
107
|
+
"vitest-package-exports": "^1.2.0",
|
|
108
|
+
"vue-tsc": "^3.2.5",
|
|
108
109
|
"yaml": "^2.8.2"
|
|
109
|
-
},
|
|
110
|
-
"pnpm": {
|
|
111
|
-
"onlyBuiltDependencies": [
|
|
112
|
-
"@parcel/watcher",
|
|
113
|
-
"better-sqlite3",
|
|
114
|
-
"esbuild",
|
|
115
|
-
"sharp",
|
|
116
|
-
"workerd"
|
|
117
|
-
],
|
|
118
|
-
"patchedDependencies": {
|
|
119
|
-
"@peculiar/x509@1.14.2": "patches/@peculiar__x509@1.14.2.patch"
|
|
120
|
-
},
|
|
121
|
-
"overrides": {
|
|
122
|
-
"reka-ui": "^2.6.1"
|
|
123
|
-
}
|
|
124
110
|
}
|
|
125
111
|
}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { AppAuthClient } from '#nuxt-better-auth';
|
|
2
|
-
import type { ActionHandleFor } from '../internal/auth-action-handles.js';
|
|
3
|
-
type SignIn = NonNullable<AppAuthClient>['signIn'];
|
|
4
|
-
export declare function useUserSignIn<MethodKey extends keyof SignIn>(method: MethodKey): ActionHandleFor<SignIn[MethodKey]>;
|
|
5
|
-
export {};
|