@nuxtjs/better-auth 0.0.0 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -0
- package/dist/module.d.mts +47 -0
- package/dist/module.json +12 -0
- package/dist/module.mjs +1468 -0
- package/dist/runtime/app/components/BetterAuthState.d.vue.ts +20 -0
- package/dist/runtime/app/components/BetterAuthState.vue +9 -0
- package/dist/runtime/app/components/BetterAuthState.vue.d.ts +20 -0
- package/dist/runtime/app/composables/runWithSessionRefresh.d.ts +1 -0
- package/dist/runtime/app/composables/runWithSessionRefresh.js +12 -0
- 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/useAuthClient.d.ts +9 -0
- package/dist/runtime/app/composables/useAuthClient.js +35 -0
- package/dist/runtime/app/composables/useAuthClientAction.d.ts +3 -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/useSignIn.js +8 -0
- package/dist/runtime/app/composables/useSignUp.d.ts +5 -0
- package/dist/runtime/app/composables/useSignUp.js +8 -0
- package/dist/runtime/app/composables/useUserSession.d.ts +23 -0
- package/dist/runtime/app/composables/useUserSession.js +247 -0
- package/dist/runtime/app/composables/useUserSessionState.d.ts +3 -0
- package/dist/runtime/app/composables/useUserSessionState.js +4 -0
- package/dist/runtime/app/internal/auth-action-error.d.ts +3 -0
- package/dist/runtime/app/internal/auth-action-error.js +33 -0
- package/dist/runtime/app/internal/auth-action-handles.d.ts +21 -0
- package/dist/runtime/app/internal/auth-action-handles.js +105 -0
- package/dist/runtime/app/internal/redirect-helpers.d.ts +4 -0
- package/dist/runtime/app/internal/redirect-helpers.js +37 -0
- package/dist/runtime/app/internal/session-fetch.d.ts +12 -0
- package/dist/runtime/app/internal/session-fetch.js +56 -0
- package/dist/runtime/app/internal/utils.d.ts +1 -0
- package/dist/runtime/app/internal/utils.js +3 -0
- package/dist/runtime/app/internal/vue-safe-auth-proxy.d.ts +3 -0
- package/dist/runtime/app/internal/vue-safe-auth-proxy.js +68 -0
- package/dist/runtime/app/internal/wrap-auth-method.d.ts +18 -0
- package/dist/runtime/app/internal/wrap-auth-method.js +69 -0
- package/dist/runtime/app/middleware/auth.global.d.ts +13 -0
- package/dist/runtime/app/middleware/auth.global.js +104 -0
- package/dist/runtime/app/pages/__better-auth-devtools.d.vue.ts +3 -0
- package/dist/runtime/app/pages/__better-auth-devtools.vue +380 -0
- package/dist/runtime/app/pages/__better-auth-devtools.vue.d.ts +3 -0
- package/dist/runtime/app/plugins/session.client.d.ts +2 -0
- package/dist/runtime/app/plugins/session.client.js +16 -0
- package/dist/runtime/app/plugins/session.server.d.ts +2 -0
- package/dist/runtime/app/plugins/session.server.js +24 -0
- package/dist/runtime/composables.d.ts +12 -0
- package/dist/runtime/composables.js +10 -0
- package/dist/runtime/config.d.ts +100 -0
- package/dist/runtime/config.js +13 -0
- package/dist/runtime/internal/auth-route-rules.d.ts +1 -0
- package/dist/runtime/internal/auth-route-rules.js +24 -0
- package/dist/runtime/server/api/_better-auth/_schema.d.ts +8 -0
- package/dist/runtime/server/api/_better-auth/_schema.js +12 -0
- package/dist/runtime/server/api/_better-auth/accounts.get.d.ts +2 -0
- package/dist/runtime/server/api/_better-auth/accounts.get.js +29 -0
- package/dist/runtime/server/api/_better-auth/config.get.d.ts +2 -0
- package/dist/runtime/server/api/_better-auth/config.get.js +58 -0
- package/dist/runtime/server/api/_better-auth/sessions.delete.d.ts +2 -0
- package/dist/runtime/server/api/_better-auth/sessions.delete.js +23 -0
- package/dist/runtime/server/api/_better-auth/sessions.get.d.ts +2 -0
- package/dist/runtime/server/api/_better-auth/sessions.get.js +44 -0
- package/dist/runtime/server/api/_better-auth/users.get.d.ts +2 -0
- package/dist/runtime/server/api/_better-auth/users.get.js +35 -0
- package/dist/runtime/server/api/auth/[...all].d.ts +2 -0
- package/dist/runtime/server/api/auth/[...all].js +6 -0
- package/dist/runtime/server/internal/nitro-compat.d.ts +1 -0
- package/dist/runtime/server/internal/nitro-compat.js +1 -0
- package/dist/runtime/server/internal/nitro2.d.ts +8 -0
- package/dist/runtime/server/internal/nitro2.js +29 -0
- package/dist/runtime/server/internal/nitro3.d.ts +10 -0
- package/dist/runtime/server/internal/nitro3.js +60 -0
- package/dist/runtime/server/middleware/route-access.d.ts +2 -0
- package/dist/runtime/server/middleware/route-access.js +29 -0
- package/dist/runtime/server/tsconfig.json +12 -0
- package/dist/runtime/server/utils/auth.d.ts +20 -0
- package/dist/runtime/server/utils/auth.js +246 -0
- package/dist/runtime/server/utils/custom-secondary-storage.d.ts +6 -0
- package/dist/runtime/server/utils/custom-secondary-storage.js +8 -0
- package/dist/runtime/server/utils/session.d.ts +8 -0
- package/dist/runtime/server/utils/session.js +280 -0
- package/dist/runtime/server/virtual-modules.d.ts +27 -0
- package/dist/runtime/types/augment.d.ts +56 -0
- package/dist/runtime/types/augment.js +0 -0
- package/dist/runtime/types.d.ts +21 -0
- package/dist/runtime/types.js +0 -0
- package/dist/runtime/utils/match-user.d.ts +2 -0
- package/dist/runtime/utils/match-user.js +13 -0
- package/dist/types.d.mts +11 -0
- package/package.json +113 -10
- package/index.js +0 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
declare var __VLS_1: {
|
|
2
|
+
loggedIn: boolean;
|
|
3
|
+
user: import("../../types.js").AuthUser | null;
|
|
4
|
+
session: import("../../types.js").AuthSession | null;
|
|
5
|
+
signOut: (options?: import("../composables/useUserSession.js").SignOutOptions) => Promise<void>;
|
|
6
|
+
}, __VLS_3: {};
|
|
7
|
+
type __VLS_Slots = {} & {
|
|
8
|
+
default?: (props: typeof __VLS_1) => any;
|
|
9
|
+
} & {
|
|
10
|
+
placeholder?: (props: typeof __VLS_3) => any;
|
|
11
|
+
};
|
|
12
|
+
declare const __VLS_base: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
13
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
14
|
+
declare const _default: typeof __VLS_export;
|
|
15
|
+
export default _default;
|
|
16
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
17
|
+
new (): {
|
|
18
|
+
$slots: S;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { useUserSession } from "../composables/useUserSession";
|
|
3
|
+
const { loggedIn, user, session, signOut, ready } = useUserSession();
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<template>
|
|
7
|
+
<slot v-if="ready" v-bind="{ loggedIn, user, session, signOut }" />
|
|
8
|
+
<slot v-else name="placeholder" />
|
|
9
|
+
</template>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
declare var __VLS_1: {
|
|
2
|
+
loggedIn: boolean;
|
|
3
|
+
user: import("../../types.js").AuthUser | null;
|
|
4
|
+
session: import("../../types.js").AuthSession | null;
|
|
5
|
+
signOut: (options?: import("../composables/useUserSession.js").SignOutOptions) => Promise<void>;
|
|
6
|
+
}, __VLS_3: {};
|
|
7
|
+
type __VLS_Slots = {} & {
|
|
8
|
+
default?: (props: typeof __VLS_1) => any;
|
|
9
|
+
} & {
|
|
10
|
+
placeholder?: (props: typeof __VLS_3) => any;
|
|
11
|
+
};
|
|
12
|
+
declare const __VLS_base: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
13
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
14
|
+
declare const _default: typeof __VLS_export;
|
|
15
|
+
export default _default;
|
|
16
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
17
|
+
new (): {
|
|
18
|
+
$slots: S;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runWithSessionRefresh<TResult>(runner: () => Promise<TResult>): Promise<TResult>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { isAuthActionErrorResult } from "../internal/auth-action-handles.js";
|
|
2
|
+
import { refreshSessionAfterAuthAction } from "../internal/wrap-auth-method.js";
|
|
3
|
+
import { useUserSession } from "./useUserSession.js";
|
|
4
|
+
export async function runWithSessionRefresh(runner) {
|
|
5
|
+
if (typeof runner !== "function")
|
|
6
|
+
throw new TypeError("runWithSessionRefresh(runner) requires an async function");
|
|
7
|
+
const auth = useUserSession();
|
|
8
|
+
const result = await runner();
|
|
9
|
+
if (!isAuthActionErrorResult(result))
|
|
10
|
+
await refreshSessionAfterAuthAction(auth.fetchSession, auth.loggedIn, auth.waitForSession);
|
|
11
|
+
return result;
|
|
12
|
+
}
|
|
@@ -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,9 @@
|
|
|
1
|
+
import type { AppAuthClient } from '#nuxt-better-auth';
|
|
2
|
+
interface RuntimeFlags {
|
|
3
|
+
client: boolean;
|
|
4
|
+
server: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare function getAuthRuntimeFlags(): RuntimeFlags;
|
|
7
|
+
export declare function useRawAuthClient(): AppAuthClient | null;
|
|
8
|
+
export declare function useAuthClient(): AppAuthClient | null;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import createAppAuthClient from "#auth/client";
|
|
2
|
+
import { useRequestURL, useRuntimeConfig } from "#imports";
|
|
3
|
+
import { createVueSafeAuthProxy } from "../internal/vue-safe-auth-proxy.js";
|
|
4
|
+
let _client = null;
|
|
5
|
+
let _clientFacade = null;
|
|
6
|
+
export function getAuthRuntimeFlags() {
|
|
7
|
+
const globalFlags = globalThis.__NUXT_BETTER_AUTH_TEST_FLAGS__;
|
|
8
|
+
if (globalFlags)
|
|
9
|
+
return globalFlags;
|
|
10
|
+
return { client: Boolean(import.meta.client), server: Boolean(import.meta.server) };
|
|
11
|
+
}
|
|
12
|
+
function getClient(baseURL) {
|
|
13
|
+
if (!_client)
|
|
14
|
+
_client = createAppAuthClient(baseURL);
|
|
15
|
+
return _client;
|
|
16
|
+
}
|
|
17
|
+
function getClientFacade(client) {
|
|
18
|
+
if (!_clientFacade)
|
|
19
|
+
_clientFacade = createVueSafeAuthProxy(client);
|
|
20
|
+
return _clientFacade;
|
|
21
|
+
}
|
|
22
|
+
export function useRawAuthClient() {
|
|
23
|
+
const runtimeFlags = getAuthRuntimeFlags();
|
|
24
|
+
if (!runtimeFlags.client)
|
|
25
|
+
return null;
|
|
26
|
+
const runtimeConfig = useRuntimeConfig();
|
|
27
|
+
const requestURL = useRequestURL();
|
|
28
|
+
const configuredSiteUrl = runtimeConfig.public.siteUrl;
|
|
29
|
+
const siteUrl = typeof configuredSiteUrl === "string" && configuredSiteUrl ? configuredSiteUrl : requestURL.origin;
|
|
30
|
+
return getClient(siteUrl);
|
|
31
|
+
}
|
|
32
|
+
export function useAuthClient() {
|
|
33
|
+
const rawClient = useRawAuthClient();
|
|
34
|
+
return rawClient ? getClientFacade(rawClient) : null;
|
|
35
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { AppAuthClient } from '#nuxt-better-auth';
|
|
2
|
+
import type { UserAuthActionHandle } from '../internal/auth-action-handles.js';
|
|
3
|
+
export declare function useAuthClientAction<TArgs extends unknown[], TResult>(select: (client: AppAuthClient) => (...args: TArgs) => Promise<TResult>): UserAuthActionHandle<TArgs, TResult>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useAction } from "./useAction.js";
|
|
2
|
+
import { useAuthClient } from "./useAuthClient.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 = useAuthClient();
|
|
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 { useRequestFetch } from '#imports';
|
|
3
|
+
type RequestFetchOptions = NonNullable<Parameters<ReturnType<typeof useRequestFetch>>[1]>;
|
|
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<Options> = RequestFetchOptions extends Options ? 'get' : AuthRequestFetchExtractedMethod<Options>;
|
|
8
|
+
type AuthRequestFetchResolvedMethod<Path extends AuthApiEndpointPath, Options> = Extract<AuthRequestFetchMethodFromOptions<Options>, AuthApiEndpointMethod<Path>> extends infer Method extends string ? Method : never;
|
|
9
|
+
type AuthRequestFetch = <Path extends AuthApiEndpointPath, Options extends RequestFetchOptions = RequestFetchOptions>(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 {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { createActionHandles } from "../internal/auth-action-handles.js";
|
|
2
|
+
import { useAuthActionNamespaces } from "./useUserSession.js";
|
|
3
|
+
export function useSignIn(method) {
|
|
4
|
+
if (method === void 0 || method === null)
|
|
5
|
+
throw new TypeError("useSignIn(method) requires a sign-in method key");
|
|
6
|
+
const handles = createActionHandles(() => useAuthActionNamespaces().signIn, "signIn");
|
|
7
|
+
return handles[method];
|
|
8
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { AppAuthClient } from '#nuxt-better-auth';
|
|
2
|
+
import type { ActionHandleFor } from '../internal/auth-action-handles.js';
|
|
3
|
+
type SignUp = NonNullable<AppAuthClient>['signUp'];
|
|
4
|
+
export declare function useSignUp<MethodKey extends keyof SignUp>(method: MethodKey): ActionHandleFor<SignUp[MethodKey]>;
|
|
5
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { createActionHandles } from "../internal/auth-action-handles.js";
|
|
2
|
+
import { useAuthActionNamespaces } from "./useUserSession.js";
|
|
3
|
+
export function useSignUp(method) {
|
|
4
|
+
if (method === void 0 || method === null)
|
|
5
|
+
throw new TypeError("useSignUp(method) requires a sign-up method key");
|
|
6
|
+
const handles = createActionHandles(() => useAuthActionNamespaces().signUp, "signUp");
|
|
7
|
+
return handles[method];
|
|
8
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ComputedRef, Ref } from 'vue';
|
|
2
|
+
import type { AuthSession, AuthUser } from '#nuxt-better-auth';
|
|
3
|
+
export interface SignOutOptions {
|
|
4
|
+
onSuccess?: () => void | Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
export interface UseUserSessionReturn {
|
|
7
|
+
session: Ref<AuthSession | null>;
|
|
8
|
+
user: Ref<AuthUser | null>;
|
|
9
|
+
loggedIn: ComputedRef<boolean>;
|
|
10
|
+
ready: ComputedRef<boolean>;
|
|
11
|
+
signOut: (options?: SignOutOptions) => Promise<void>;
|
|
12
|
+
waitForSession: () => Promise<void>;
|
|
13
|
+
fetchSession: (options?: {
|
|
14
|
+
headers?: HeadersInit;
|
|
15
|
+
force?: boolean;
|
|
16
|
+
}) => Promise<void>;
|
|
17
|
+
updateUser: (updates: Partial<AuthUser>) => Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
export declare function useUserSession(): UseUserSessionReturn;
|
|
20
|
+
export declare function useAuthActionNamespaces(): {
|
|
21
|
+
signIn: any;
|
|
22
|
+
signUp: any;
|
|
23
|
+
};
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { computed, navigateTo, nextTick, useNuxtApp, useRequestURL, useRuntimeConfig, useState, watch } from "#imports";
|
|
2
|
+
import { normalizeAuthActionError } from "../internal/auth-action-error.js";
|
|
3
|
+
import { resolvePostAuthSuccessRedirect, withFallbackSocialCallbackURL } from "../internal/redirect-helpers.js";
|
|
4
|
+
import { fetchSessionClient, fetchSessionServer, stripToken } from "../internal/session-fetch.js";
|
|
5
|
+
import { isRecord } from "../internal/utils.js";
|
|
6
|
+
import { createVueSafeAuthFacade, isAuthProxyProbeKey } from "../internal/vue-safe-auth-proxy.js";
|
|
7
|
+
import { wrapAuthMethod } from "../internal/wrap-auth-method.js";
|
|
8
|
+
import { getAuthRuntimeFlags, useRawAuthClient } from "./useAuthClient.js";
|
|
9
|
+
let _sessionSignalListenerBound = false;
|
|
10
|
+
let _signOutPromise = null;
|
|
11
|
+
function createServerOnlyActionNamespace(path) {
|
|
12
|
+
return new Proxy({}, {
|
|
13
|
+
get(_target, prop) {
|
|
14
|
+
if (isAuthProxyProbeKey(prop))
|
|
15
|
+
return void 0;
|
|
16
|
+
const key = prop;
|
|
17
|
+
return async () => {
|
|
18
|
+
throw new Error(`${path}.${key}() can only be called on client-side`);
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
const _signInServerOnly = createServerOnlyActionNamespace("signIn");
|
|
24
|
+
const _signUpServerOnly = createServerOnlyActionNamespace("signUp");
|
|
25
|
+
function ensureSessionSignalListener(client, onSignal) {
|
|
26
|
+
if (_sessionSignalListenerBound)
|
|
27
|
+
return;
|
|
28
|
+
const store = client.$store;
|
|
29
|
+
if (!isRecord(store))
|
|
30
|
+
return;
|
|
31
|
+
const listen = store.listen;
|
|
32
|
+
if (typeof listen !== "function")
|
|
33
|
+
return;
|
|
34
|
+
_sessionSignalListenerBound = true;
|
|
35
|
+
const listenFn = listen;
|
|
36
|
+
listenFn("$sessionSignal", async () => {
|
|
37
|
+
try {
|
|
38
|
+
await onSignal();
|
|
39
|
+
} catch {
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
export function useUserSession() {
|
|
44
|
+
const runtimeFlags = getAuthRuntimeFlags();
|
|
45
|
+
const runtimeConfig = useRuntimeConfig();
|
|
46
|
+
const nuxtApp = useNuxtApp();
|
|
47
|
+
const rawClient = useRawAuthClient();
|
|
48
|
+
const session = useState("auth:session", () => null);
|
|
49
|
+
const user = useState("auth:user", () => null);
|
|
50
|
+
const authReady = useState("auth:ready", () => false);
|
|
51
|
+
const prerenderReadyResetQueued = useState("auth:prerender-ready-reset-queued", () => false);
|
|
52
|
+
const hydrationReconcileQueued = useState("auth:hydration-reconcile-queued", () => false);
|
|
53
|
+
const ready = computed(() => authReady.value);
|
|
54
|
+
const loggedIn = computed(() => Boolean(session.value && user.value));
|
|
55
|
+
const isPrerenderedPayload = computed(() => Boolean(nuxtApp.payload.prerenderedAt || nuxtApp.payload.isCached));
|
|
56
|
+
const isPrerenderHydrationEmptySnapshot = computed(() => {
|
|
57
|
+
if (!runtimeFlags.client)
|
|
58
|
+
return false;
|
|
59
|
+
if (!nuxtApp.isHydrating || !nuxtApp.payload.serverRendered || !isPrerenderedPayload.value)
|
|
60
|
+
return false;
|
|
61
|
+
return !session.value && !user.value;
|
|
62
|
+
});
|
|
63
|
+
const skipHydratedSsrGetSession = computed(() => {
|
|
64
|
+
const authConfig = runtimeConfig.public.auth;
|
|
65
|
+
return Boolean(authConfig?.session?.skipHydratedSsrGetSession);
|
|
66
|
+
});
|
|
67
|
+
const shouldSkipInitialClientSessionFetch = computed(() => {
|
|
68
|
+
if (!skipHydratedSsrGetSession.value)
|
|
69
|
+
return false;
|
|
70
|
+
if (!runtimeFlags.client)
|
|
71
|
+
return false;
|
|
72
|
+
if (!nuxtApp.payload.serverRendered)
|
|
73
|
+
return false;
|
|
74
|
+
if (isPrerenderedPayload.value)
|
|
75
|
+
return false;
|
|
76
|
+
return Boolean(session.value && user.value);
|
|
77
|
+
});
|
|
78
|
+
if (isPrerenderHydrationEmptySnapshot.value && authReady.value && !prerenderReadyResetQueued.value) {
|
|
79
|
+
prerenderReadyResetQueued.value = true;
|
|
80
|
+
nuxtApp.hook("app:suspense:resolve", () => {
|
|
81
|
+
try {
|
|
82
|
+
if (!session.value && !user.value && authReady.value)
|
|
83
|
+
authReady.value = false;
|
|
84
|
+
} finally {
|
|
85
|
+
prerenderReadyResetQueued.value = false;
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
if (shouldSkipInitialClientSessionFetch.value && !authReady.value)
|
|
90
|
+
authReady.value = true;
|
|
91
|
+
function clearSession() {
|
|
92
|
+
session.value = null;
|
|
93
|
+
user.value = null;
|
|
94
|
+
}
|
|
95
|
+
async function fetchSession(options = {}) {
|
|
96
|
+
if (runtimeFlags.server)
|
|
97
|
+
return fetchSessionServer(session, user, authReady, options);
|
|
98
|
+
if (rawClient)
|
|
99
|
+
return fetchSessionClient(rawClient, session, user, authReady, options);
|
|
100
|
+
}
|
|
101
|
+
async function updateUser(updates) {
|
|
102
|
+
if (!user.value)
|
|
103
|
+
return;
|
|
104
|
+
const previousUser = user.value;
|
|
105
|
+
user.value = { ...user.value, ...updates };
|
|
106
|
+
if (!rawClient)
|
|
107
|
+
return;
|
|
108
|
+
try {
|
|
109
|
+
const clientWithUpdateUser = rawClient;
|
|
110
|
+
const result = await clientWithUpdateUser.updateUser(updates);
|
|
111
|
+
if (result?.error) {
|
|
112
|
+
if (result.error instanceof Error)
|
|
113
|
+
throw result.error;
|
|
114
|
+
const normalizedError = normalizeAuthActionError(result.error);
|
|
115
|
+
throw new Error(normalizedError.message);
|
|
116
|
+
}
|
|
117
|
+
} catch (error) {
|
|
118
|
+
user.value = previousUser;
|
|
119
|
+
if (!(error instanceof Error)) {
|
|
120
|
+
const normalizedError = normalizeAuthActionError(error);
|
|
121
|
+
throw new Error(normalizedError.message);
|
|
122
|
+
}
|
|
123
|
+
throw error;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (runtimeFlags.client && rawClient && !shouldSkipInitialClientSessionFetch.value) {
|
|
127
|
+
const clientSession = rawClient.useSession();
|
|
128
|
+
watch(
|
|
129
|
+
() => clientSession.value,
|
|
130
|
+
(newSession) => {
|
|
131
|
+
const shouldWaitForPrerenderResolution = isPrerenderHydrationEmptySnapshot.value && !newSession?.data?.session && !newSession?.data?.user;
|
|
132
|
+
if (shouldWaitForPrerenderResolution)
|
|
133
|
+
return;
|
|
134
|
+
if (newSession?.data?.session && newSession?.data?.user) {
|
|
135
|
+
session.value = stripToken(newSession.data.session);
|
|
136
|
+
user.value = newSession.data.user;
|
|
137
|
+
} else if (!newSession?.isPending && !newSession?.isRefetching) {
|
|
138
|
+
const isHydrationEmptySnapshot = nuxtApp.isHydrating && nuxtApp.payload.serverRendered && Boolean(session.value && user.value) && !newSession?.data?.session && !newSession?.data?.user;
|
|
139
|
+
if (isHydrationEmptySnapshot) {
|
|
140
|
+
if (!hydrationReconcileQueued.value) {
|
|
141
|
+
hydrationReconcileQueued.value = true;
|
|
142
|
+
nuxtApp.hook("app:mounted", async () => {
|
|
143
|
+
await fetchSession({ force: true });
|
|
144
|
+
hydrationReconcileQueued.value = false;
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
clearSession();
|
|
150
|
+
}
|
|
151
|
+
if (!authReady.value && !newSession?.isPending && !newSession?.isRefetching)
|
|
152
|
+
authReady.value = true;
|
|
153
|
+
},
|
|
154
|
+
{ immediate: true, deep: true }
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
function waitForSession() {
|
|
158
|
+
return new Promise((resolve) => {
|
|
159
|
+
if (loggedIn.value) {
|
|
160
|
+
resolve();
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const unwatch = watch(loggedIn, (isLoggedIn) => {
|
|
164
|
+
if (isLoggedIn) {
|
|
165
|
+
unwatch();
|
|
166
|
+
resolve();
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
setTimeout(() => {
|
|
170
|
+
unwatch();
|
|
171
|
+
resolve();
|
|
172
|
+
}, 5e3);
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
if (runtimeFlags.client && rawClient && shouldSkipInitialClientSessionFetch.value) {
|
|
176
|
+
ensureSessionSignalListener(rawClient, () => fetchSession({ force: true }));
|
|
177
|
+
}
|
|
178
|
+
async function signOut(options) {
|
|
179
|
+
if (!rawClient)
|
|
180
|
+
throw new Error("signOut can only be called on client-side");
|
|
181
|
+
if (_signOutPromise) {
|
|
182
|
+
await _signOutPromise;
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
_signOutPromise = (async () => {
|
|
186
|
+
await rawClient.signOut();
|
|
187
|
+
clearSession();
|
|
188
|
+
if (options?.onSuccess) {
|
|
189
|
+
await options.onSuccess();
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const authConfig = runtimeConfig.public.auth;
|
|
193
|
+
const logoutRedirect = authConfig?.redirects?.logout;
|
|
194
|
+
if (logoutRedirect) {
|
|
195
|
+
await nextTick();
|
|
196
|
+
await navigateTo(logoutRedirect);
|
|
197
|
+
}
|
|
198
|
+
})().finally(() => {
|
|
199
|
+
_signOutPromise = null;
|
|
200
|
+
});
|
|
201
|
+
await _signOutPromise;
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
session,
|
|
205
|
+
user,
|
|
206
|
+
loggedIn,
|
|
207
|
+
ready,
|
|
208
|
+
signOut,
|
|
209
|
+
waitForSession,
|
|
210
|
+
fetchSession,
|
|
211
|
+
updateUser
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
export function useAuthActionNamespaces() {
|
|
215
|
+
const rawClient = useRawAuthClient();
|
|
216
|
+
const auth = useUserSession();
|
|
217
|
+
const requestURL = useRequestURL();
|
|
218
|
+
const wrapDeps = {
|
|
219
|
+
fetchSession: auth.fetchSession,
|
|
220
|
+
loggedIn: auth.loggedIn,
|
|
221
|
+
waitForSession: auth.waitForSession,
|
|
222
|
+
resolvePostAuthSuccessRedirect: () => resolvePostAuthSuccessRedirect(requestURL)
|
|
223
|
+
};
|
|
224
|
+
const signIn = rawClient?.signIn ? createVueSafeAuthFacade((prop) => {
|
|
225
|
+
const targetRecord = rawClient.signIn;
|
|
226
|
+
const method = targetRecord[prop];
|
|
227
|
+
if (typeof method !== "function")
|
|
228
|
+
return method;
|
|
229
|
+
const isRedirectOAuthSignIn = prop === "social" || prop === "oauth2";
|
|
230
|
+
return wrapAuthMethod(
|
|
231
|
+
(...args) => targetRecord[prop](...args),
|
|
232
|
+
wrapDeps,
|
|
233
|
+
isRedirectOAuthSignIn ? {
|
|
234
|
+
shouldSkipSessionSync: (data) => !isRecord(data) || data.disableRedirect !== true,
|
|
235
|
+
transformData: (data) => withFallbackSocialCallbackURL(data, requestURL)
|
|
236
|
+
} : {}
|
|
237
|
+
);
|
|
238
|
+
}) : _signInServerOnly;
|
|
239
|
+
const signUp = rawClient?.signUp ? createVueSafeAuthFacade((prop) => {
|
|
240
|
+
const targetRecord = rawClient.signUp;
|
|
241
|
+
const method = targetRecord[prop];
|
|
242
|
+
if (typeof method !== "function")
|
|
243
|
+
return method;
|
|
244
|
+
return wrapAuthMethod((...args) => targetRecord[prop](...args), wrapDeps);
|
|
245
|
+
}) : _signUpServerOnly;
|
|
246
|
+
return { signIn, signUp };
|
|
247
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { isRecord } from "./utils.js";
|
|
2
|
+
export const DEFAULT_AUTH_ACTION_ERROR_MESSAGE = "Request failed. Please try again.";
|
|
3
|
+
function getMessage(value) {
|
|
4
|
+
if (value instanceof Error)
|
|
5
|
+
return value.message;
|
|
6
|
+
if (typeof value === "string")
|
|
7
|
+
return value;
|
|
8
|
+
if (isRecord(value) && typeof value.message === "string")
|
|
9
|
+
return value.message;
|
|
10
|
+
return DEFAULT_AUTH_ACTION_ERROR_MESSAGE;
|
|
11
|
+
}
|
|
12
|
+
function getCode(value) {
|
|
13
|
+
if (!isRecord(value))
|
|
14
|
+
return void 0;
|
|
15
|
+
return typeof value.code === "string" ? value.code : void 0;
|
|
16
|
+
}
|
|
17
|
+
function getStatus(value) {
|
|
18
|
+
if (!isRecord(value))
|
|
19
|
+
return void 0;
|
|
20
|
+
if (typeof value.status === "number")
|
|
21
|
+
return value.status;
|
|
22
|
+
if (typeof value.statusCode === "number")
|
|
23
|
+
return value.statusCode;
|
|
24
|
+
return void 0;
|
|
25
|
+
}
|
|
26
|
+
export function normalizeAuthActionError(error) {
|
|
27
|
+
return {
|
|
28
|
+
message: getMessage(error),
|
|
29
|
+
code: getCode(error),
|
|
30
|
+
status: getStatus(error),
|
|
31
|
+
raw: error
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Ref } from 'vue';
|
|
2
|
+
import type { AuthActionError } from '../../types.js';
|
|
3
|
+
export type UserAuthActionStatus = 'idle' | 'pending' | 'success' | 'error';
|
|
4
|
+
export interface UserAuthActionHandle<TArgs extends unknown[], TResult> {
|
|
5
|
+
execute: (...args: TArgs) => Promise<void>;
|
|
6
|
+
status: Ref<UserAuthActionStatus>;
|
|
7
|
+
data: Ref<TResult | null>;
|
|
8
|
+
error: Ref<AuthActionError | null>;
|
|
9
|
+
}
|
|
10
|
+
export interface CreateActionHandleOptions {
|
|
11
|
+
keepPendingOnRedirect?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export type ActionHandleFor<T> = T extends (...args: infer A) => Promise<infer R> ? UserAuthActionHandle<A, R> : never;
|
|
14
|
+
export type ActionHandleMap<T> = {
|
|
15
|
+
[K in keyof T]: ActionHandleFor<T[K]>;
|
|
16
|
+
};
|
|
17
|
+
export declare function isAuthActionErrorResult(value: unknown): value is {
|
|
18
|
+
error: unknown;
|
|
19
|
+
};
|
|
20
|
+
export declare function createActionHandle<TArgs extends unknown[], TResult>(getMethod: () => (...args: TArgs) => Promise<TResult>, options?: CreateActionHandleOptions): UserAuthActionHandle<TArgs, TResult>;
|
|
21
|
+
export declare function createActionHandles<T extends object>(getTarget: () => T, targetName: string): ActionHandleMap<T>;
|