@onmax/nuxt-better-auth 0.0.2-alpha.30 → 0.0.2-alpha.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -17
- package/dist/module.d.mts +0 -9
- package/dist/module.json +2 -2
- package/dist/module.mjs +668 -267
- package/dist/runtime/app/components/BetterAuthState.d.vue.ts +4 -4
- package/dist/runtime/app/components/BetterAuthState.vue +1 -1
- package/dist/runtime/app/components/BetterAuthState.vue.d.ts +4 -4
- package/dist/runtime/app/composables/useAuthClient.d.ts +9 -0
- package/dist/runtime/app/composables/useAuthClient.js +34 -0
- package/dist/runtime/app/composables/useAuthClientAction.d.ts +1 -3
- package/dist/runtime/app/composables/useAuthClientAction.js +2 -2
- package/dist/runtime/app/composables/useAuthRequestFetch.d.ts +1 -1
- package/dist/runtime/app/composables/useSignIn.js +2 -2
- package/dist/runtime/app/composables/useSignUp.js +2 -2
- package/dist/runtime/app/composables/useUserSession.d.ts +5 -4
- package/dist/runtime/app/composables/useUserSession.js +91 -218
- package/dist/runtime/app/composables/useUserSessionState.d.ts +3 -0
- package/dist/runtime/app/composables/useUserSessionState.js +4 -0
- package/dist/runtime/app/internal/auth-action-error.js +1 -3
- package/dist/runtime/app/internal/auth-action-handles.js +1 -3
- package/dist/runtime/app/internal/redirect-helpers.d.ts +4 -0
- package/dist/runtime/app/internal/redirect-helpers.js +37 -0
- package/dist/runtime/app/internal/session-fetch.d.ts +12 -0
- package/dist/runtime/app/internal/session-fetch.js +56 -0
- package/dist/runtime/app/internal/utils.d.ts +1 -0
- package/dist/runtime/app/internal/utils.js +3 -0
- package/dist/runtime/app/internal/vue-safe-auth-proxy.d.ts +3 -0
- package/dist/runtime/app/internal/vue-safe-auth-proxy.js +68 -0
- package/dist/runtime/app/internal/wrap-auth-method.d.ts +15 -0
- package/dist/runtime/app/internal/wrap-auth-method.js +66 -0
- package/dist/runtime/app/middleware/auth.global.js +5 -4
- package/dist/runtime/app/plugins/session.client.js +2 -1
- package/dist/runtime/composables.d.ts +11 -0
- package/dist/runtime/composables.js +9 -0
- package/dist/runtime/config.d.ts +8 -6
- package/dist/runtime/config.js +3 -1
- package/dist/runtime/server/api/_better-auth/_schema.d.ts +1 -5
- package/dist/runtime/server/api/_better-auth/_schema.js +2 -1
- package/dist/runtime/server/api/_better-auth/accounts.get.d.ts +2 -2
- package/dist/runtime/server/api/_better-auth/config.get.js +1 -1
- package/dist/runtime/server/api/_better-auth/sessions.get.d.ts +2 -2
- package/dist/runtime/server/api/_better-auth/users.get.d.ts +2 -2
- package/dist/runtime/server/middleware/route-access.js +1 -1
- package/dist/runtime/server/utils/auth.d.ts +13 -2
- package/dist/runtime/server/utils/auth.js +42 -16
- package/dist/runtime/server/utils/session.d.ts +3 -1
- package/dist/runtime/server/utils/session.js +175 -1
- package/dist/runtime/server/virtual-modules.d.ts +5 -0
- package/dist/runtime/types/augment.d.ts +1 -3
- package/dist/runtime/types.d.ts +1 -1
- package/package.json +33 -26
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { useRequestFetch, useRequestHeaders } from "#imports";
|
|
2
|
+
import { normalizeAuthActionError } from "./auth-action-error.js";
|
|
3
|
+
export function stripToken(session) {
|
|
4
|
+
const { token: _, ...safe } = session;
|
|
5
|
+
return safe;
|
|
6
|
+
}
|
|
7
|
+
function isExpectedSignedOutSessionError(error) {
|
|
8
|
+
const normalizedError = normalizeAuthActionError(error);
|
|
9
|
+
if (normalizedError.status === 401)
|
|
10
|
+
return true;
|
|
11
|
+
return normalizedError.code === "UNAUTHORIZED";
|
|
12
|
+
}
|
|
13
|
+
export async function fetchSessionServer(session, user, authReady, options = {}) {
|
|
14
|
+
try {
|
|
15
|
+
const headers = options.headers || useRequestHeaders(["cookie"]);
|
|
16
|
+
const requestFetch = useRequestFetch();
|
|
17
|
+
const data = await requestFetch("/api/auth/get-session", { headers });
|
|
18
|
+
if (data?.session && data?.user) {
|
|
19
|
+
session.value = stripToken(data.session);
|
|
20
|
+
user.value = data.user;
|
|
21
|
+
} else {
|
|
22
|
+
session.value = null;
|
|
23
|
+
user.value = null;
|
|
24
|
+
}
|
|
25
|
+
} catch {
|
|
26
|
+
session.value = null;
|
|
27
|
+
user.value = null;
|
|
28
|
+
} finally {
|
|
29
|
+
if (!authReady.value)
|
|
30
|
+
authReady.value = true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export async function fetchSessionClient(client, session, user, authReady, options = {}) {
|
|
34
|
+
try {
|
|
35
|
+
const headers = options.headers || useRequestHeaders(["cookie"]);
|
|
36
|
+
const fetchOptions = headers ? { headers } : void 0;
|
|
37
|
+
const query = options.force ? { disableCookieCache: true } : void 0;
|
|
38
|
+
const result = await client.getSession({ query }, fetchOptions);
|
|
39
|
+
const data = result.data;
|
|
40
|
+
if (data?.session && data?.user) {
|
|
41
|
+
session.value = stripToken(data.session);
|
|
42
|
+
user.value = data.user;
|
|
43
|
+
} else {
|
|
44
|
+
session.value = null;
|
|
45
|
+
user.value = null;
|
|
46
|
+
}
|
|
47
|
+
} catch (error) {
|
|
48
|
+
session.value = null;
|
|
49
|
+
user.value = null;
|
|
50
|
+
if (!isExpectedSignedOutSessionError(error))
|
|
51
|
+
console.error("[nuxt-better-auth] Failed to fetch session:", error);
|
|
52
|
+
} finally {
|
|
53
|
+
if (!authReady.value)
|
|
54
|
+
authReady.value = true;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const promiseProbeKeys = /* @__PURE__ */ new Set(["then", "catch", "finally"]);
|
|
2
|
+
export function isAuthProxyProbeKey(prop) {
|
|
3
|
+
return typeof prop !== "string" || promiseProbeKeys.has(prop) || prop.startsWith("__v");
|
|
4
|
+
}
|
|
5
|
+
function isObjectLike(value) {
|
|
6
|
+
return typeof value === "object" && value !== null || typeof value === "function";
|
|
7
|
+
}
|
|
8
|
+
export function createVueSafeAuthFacade(resolve) {
|
|
9
|
+
const propertyCache = /* @__PURE__ */ new Map();
|
|
10
|
+
const facadeTarget = {};
|
|
11
|
+
Object.defineProperty(facadeTarget, "__v_skip", {
|
|
12
|
+
value: true,
|
|
13
|
+
configurable: true
|
|
14
|
+
});
|
|
15
|
+
return new Proxy(facadeTarget, {
|
|
16
|
+
get(_target, prop, receiver) {
|
|
17
|
+
if (prop === "__v_skip")
|
|
18
|
+
return true;
|
|
19
|
+
if (isAuthProxyProbeKey(prop))
|
|
20
|
+
return void 0;
|
|
21
|
+
if (propertyCache.has(prop))
|
|
22
|
+
return propertyCache.get(prop);
|
|
23
|
+
const value = resolve(prop, receiver);
|
|
24
|
+
propertyCache.set(prop, value);
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
export function createVueSafeAuthProxy(target) {
|
|
30
|
+
if (!isObjectLike(target))
|
|
31
|
+
return target;
|
|
32
|
+
const cache = /* @__PURE__ */ new WeakMap();
|
|
33
|
+
const wrap = (value) => {
|
|
34
|
+
if (!isObjectLike(value))
|
|
35
|
+
return value;
|
|
36
|
+
const cached = cache.get(value);
|
|
37
|
+
if (cached)
|
|
38
|
+
return cached;
|
|
39
|
+
const propertyCache = /* @__PURE__ */ new Map();
|
|
40
|
+
const handler = {
|
|
41
|
+
get(target2, prop, receiver) {
|
|
42
|
+
if (prop === "__v_skip")
|
|
43
|
+
return true;
|
|
44
|
+
if (isAuthProxyProbeKey(prop))
|
|
45
|
+
return void 0;
|
|
46
|
+
if (propertyCache.has(prop))
|
|
47
|
+
return propertyCache.get(prop);
|
|
48
|
+
const wrapped = wrap(Reflect.get(target2, prop, receiver));
|
|
49
|
+
propertyCache.set(prop, wrapped);
|
|
50
|
+
return wrapped;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
if (typeof value === "function") {
|
|
54
|
+
handler.apply = (target2, thisArg, args) => Reflect.apply(target2, thisArg, args);
|
|
55
|
+
}
|
|
56
|
+
const proxy = new Proxy(value, handler);
|
|
57
|
+
cache.set(value, proxy);
|
|
58
|
+
return proxy;
|
|
59
|
+
};
|
|
60
|
+
const createRootFacade = (value) => {
|
|
61
|
+
if (!isObjectLike(value))
|
|
62
|
+
return value;
|
|
63
|
+
const proxy = createVueSafeAuthFacade((prop, receiver) => wrap(Reflect.get(value, prop, receiver)));
|
|
64
|
+
cache.set(value, proxy);
|
|
65
|
+
return proxy;
|
|
66
|
+
};
|
|
67
|
+
return createRootFacade(target);
|
|
68
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ComputedRef } from 'vue';
|
|
2
|
+
export declare function wrapOnSuccess(fetchSession: (options?: {
|
|
3
|
+
force?: boolean;
|
|
4
|
+
}) => Promise<void>, loggedIn: ComputedRef<boolean>, waitForSession: () => Promise<void>, cb: (ctx: unknown) => void | Promise<void>): (ctx: unknown) => Promise<void>;
|
|
5
|
+
export declare function wrapAuthMethod<T extends (...args: unknown[]) => Promise<unknown>>(method: T, deps: {
|
|
6
|
+
fetchSession: (options?: {
|
|
7
|
+
force?: boolean;
|
|
8
|
+
}) => Promise<void>;
|
|
9
|
+
loggedIn: ComputedRef<boolean>;
|
|
10
|
+
waitForSession: () => Promise<void>;
|
|
11
|
+
resolvePostAuthSuccessRedirect: () => (() => Promise<void>) | undefined;
|
|
12
|
+
}, wrapOptions?: {
|
|
13
|
+
shouldSkipSessionSync?: (data: unknown, options: unknown) => boolean;
|
|
14
|
+
transformData?: (data: unknown, options: unknown) => unknown;
|
|
15
|
+
}): T;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { nextTick } from "#imports";
|
|
2
|
+
import { isRecord } from "./utils.js";
|
|
3
|
+
export function wrapOnSuccess(fetchSession, loggedIn, waitForSession, cb) {
|
|
4
|
+
return async (ctx) => {
|
|
5
|
+
await fetchSession({ force: true });
|
|
6
|
+
if (!loggedIn.value)
|
|
7
|
+
await waitForSession();
|
|
8
|
+
await nextTick();
|
|
9
|
+
await cb(ctx);
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export function wrapAuthMethod(method, deps, wrapOptions = {}) {
|
|
13
|
+
return (async (...args) => {
|
|
14
|
+
const originalData = args[0];
|
|
15
|
+
const options = args[1];
|
|
16
|
+
const data = wrapOptions.transformData?.(originalData, options) ?? originalData;
|
|
17
|
+
const dataRecord = isRecord(data) ? data : void 0;
|
|
18
|
+
const optionsRecord = isRecord(options) ? options : void 0;
|
|
19
|
+
if (wrapOptions.shouldSkipSessionSync?.(data, options))
|
|
20
|
+
return method(data, options);
|
|
21
|
+
const fetchOptions = isRecord(dataRecord?.fetchOptions) ? dataRecord.fetchOptions : void 0;
|
|
22
|
+
const nestedOnSuccess = fetchOptions?.onSuccess;
|
|
23
|
+
const topLevelOnSuccess = optionsRecord?.onSuccess;
|
|
24
|
+
const fallbackOnSuccess = deps.resolvePostAuthSuccessRedirect();
|
|
25
|
+
const wrappedFallbackOnSuccess = fallbackOnSuccess && wrapOnSuccess(deps.fetchSession, deps.loggedIn, deps.waitForSession, async () => {
|
|
26
|
+
if (!deps.loggedIn.value)
|
|
27
|
+
return;
|
|
28
|
+
await fallbackOnSuccess();
|
|
29
|
+
});
|
|
30
|
+
if (typeof nestedOnSuccess === "function") {
|
|
31
|
+
const nextData = {
|
|
32
|
+
...dataRecord,
|
|
33
|
+
fetchOptions: {
|
|
34
|
+
...fetchOptions,
|
|
35
|
+
onSuccess: wrapOnSuccess(deps.fetchSession, deps.loggedIn, deps.waitForSession, nestedOnSuccess)
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
return method(nextData, options);
|
|
39
|
+
}
|
|
40
|
+
if (typeof topLevelOnSuccess === "function") {
|
|
41
|
+
const nextOptions = {
|
|
42
|
+
...optionsRecord,
|
|
43
|
+
onSuccess: wrapOnSuccess(deps.fetchSession, deps.loggedIn, deps.waitForSession, topLevelOnSuccess)
|
|
44
|
+
};
|
|
45
|
+
return method(data, nextOptions);
|
|
46
|
+
}
|
|
47
|
+
if (wrappedFallbackOnSuccess) {
|
|
48
|
+
if (fetchOptions) {
|
|
49
|
+
const nextData = {
|
|
50
|
+
...dataRecord,
|
|
51
|
+
fetchOptions: {
|
|
52
|
+
...fetchOptions,
|
|
53
|
+
onSuccess: wrappedFallbackOnSuccess
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
return method(nextData, options);
|
|
57
|
+
}
|
|
58
|
+
const nextOptions = {
|
|
59
|
+
...optionsRecord,
|
|
60
|
+
onSuccess: wrappedFallbackOnSuccess
|
|
61
|
+
};
|
|
62
|
+
return method(data, nextOptions);
|
|
63
|
+
}
|
|
64
|
+
return method(data, options);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { createError, defineNuxtRouteMiddleware, getRouteRules, navigateTo, useNuxtApp, useRequestHeaders, useRuntimeConfig, useUserSession } from "#imports";
|
|
2
1
|
import { defu } from "defu";
|
|
3
2
|
import { createRouter, toRouteMatcher } from "radix3";
|
|
3
|
+
import { createError, defineNuxtRouteMiddleware, getRouteRules, navigateTo, useNuxtApp, useRequestHeaders, useRuntimeConfig } from "#imports";
|
|
4
4
|
import { matchesUser } from "../../utils/match-user.js";
|
|
5
|
+
import { useUserSession } from "../composables/useUserSession.js";
|
|
5
6
|
let authRouteRulesPromise = null;
|
|
6
7
|
let routeRulesMatcherPromise = null;
|
|
7
8
|
export default defineNuxtRouteMiddleware(async (to) => {
|
|
@@ -25,13 +26,13 @@ export default defineNuxtRouteMiddleware(async (to) => {
|
|
|
25
26
|
return;
|
|
26
27
|
const config = useRuntimeConfig().public.auth;
|
|
27
28
|
const { fetchSession, user, loggedIn } = useUserSession();
|
|
28
|
-
|
|
29
|
+
const mode = typeof auth === "string" ? auth : auth?.only ?? "user";
|
|
30
|
+
const redirectTo = typeof auth === "object" ? auth.redirectTo : void 0;
|
|
31
|
+
if (!loggedIn.value || mode === "guest") {
|
|
29
32
|
const headers = import.meta.server ? useRequestHeaders(["cookie"]) : void 0;
|
|
30
33
|
const isHydratedPrerenderPayload = (import.meta.client || !import.meta.server) && nuxtApp.isHydrating && Boolean(nuxtApp.payload.prerenderedAt || nuxtApp.payload.isCached);
|
|
31
34
|
await fetchSession({ headers, ...isHydratedPrerenderPayload ? { force: true } : {} });
|
|
32
35
|
}
|
|
33
|
-
const mode = typeof auth === "string" ? auth : auth?.only ?? "user";
|
|
34
|
-
const redirectTo = typeof auth === "object" ? auth.redirectTo : void 0;
|
|
35
36
|
if (mode === "guest") {
|
|
36
37
|
if (loggedIn.value)
|
|
37
38
|
return navigateTo(redirectTo ?? config?.redirects?.guest ?? "/");
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { defineNuxtPlugin
|
|
1
|
+
import { defineNuxtPlugin } from "#imports";
|
|
2
|
+
import { useUserSession } from "../composables/useUserSession.js";
|
|
2
3
|
export default defineNuxtPlugin(async (nuxtApp) => {
|
|
3
4
|
const { fetchSession } = useUserSession();
|
|
4
5
|
const safeFetch = async () => {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { useAction } from './app/composables/useAction.js';
|
|
2
|
+
export { useAuthAsyncData } from './app/composables/useAuthAsyncData.js';
|
|
3
|
+
export { useAuthClient } from './app/composables/useAuthClient.js';
|
|
4
|
+
export { useAuthClientAction } from './app/composables/useAuthClientAction.js';
|
|
5
|
+
export { useAuthRequestFetch } from './app/composables/useAuthRequestFetch.js';
|
|
6
|
+
export { useSignIn } from './app/composables/useSignIn.js';
|
|
7
|
+
export { useSignUp } from './app/composables/useSignUp.js';
|
|
8
|
+
export { useUserSession } from './app/composables/useUserSession.js';
|
|
9
|
+
export type { SignOutOptions, UseUserSessionReturn } from './app/composables/useUserSession.js';
|
|
10
|
+
export { useUserSessionState } from './app/composables/useUserSessionState.js';
|
|
11
|
+
export type { UseUserSessionStateReturn } from './app/composables/useUserSessionState.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { useAction } from "./app/composables/useAction.js";
|
|
2
|
+
export { useAuthAsyncData } from "./app/composables/useAuthAsyncData.js";
|
|
3
|
+
export { useAuthClient } from "./app/composables/useAuthClient.js";
|
|
4
|
+
export { useAuthClientAction } from "./app/composables/useAuthClientAction.js";
|
|
5
|
+
export { useAuthRequestFetch } from "./app/composables/useAuthRequestFetch.js";
|
|
6
|
+
export { useSignIn } from "./app/composables/useSignIn.js";
|
|
7
|
+
export { useSignUp } from "./app/composables/useSignUp.js";
|
|
8
|
+
export { useUserSession } from "./app/composables/useUserSession.js";
|
|
9
|
+
export { useUserSessionState } from "./app/composables/useUserSessionState.js";
|
package/dist/runtime/config.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { BetterAuthOptions, BetterAuthPlugin } from 'better-auth';
|
|
2
2
|
import type { BetterAuthClientOptions } from 'better-auth/client';
|
|
3
|
-
import type {
|
|
4
|
-
import type { ServerAuthContext } from './types/augment.js';
|
|
3
|
+
import type { Casing } from 'drizzle-orm/utils';
|
|
4
|
+
import type { ServerAuthContext as BaseServerAuthContext } from './types/augment.js';
|
|
5
5
|
import { createAuthClient } from 'better-auth/vue';
|
|
6
|
-
export
|
|
6
|
+
export interface ServerAuthContextExtension {
|
|
7
|
+
}
|
|
8
|
+
export type ServerAuthContext = BaseServerAuthContext & ServerAuthContextExtension;
|
|
7
9
|
export interface ClientAuthContext {
|
|
8
10
|
siteUrl: string;
|
|
9
11
|
}
|
|
@@ -20,9 +22,9 @@ export type EffectiveDatabaseProviderId = 'user' | ModuleDatabaseProviderId;
|
|
|
20
22
|
export interface BetterAuthModuleOptions {
|
|
21
23
|
/** Client-only mode - skip server setup for external auth backends */
|
|
22
24
|
clientOnly?: boolean;
|
|
23
|
-
/** Server config path
|
|
25
|
+
/** Server config path. Relative paths resolve from the layer that declares them. Default: 'server/auth.config' */
|
|
24
26
|
serverConfig?: string;
|
|
25
|
-
/** Client config path
|
|
27
|
+
/** Client config path. Relative paths resolve from the layer that declares them. Default: 'app/auth.config' */
|
|
26
28
|
clientConfig?: string;
|
|
27
29
|
redirects?: {
|
|
28
30
|
/** Where to redirect unauthenticated users. Default: '/login' */
|
|
@@ -69,7 +71,7 @@ export interface BetterAuthModuleOptions {
|
|
|
69
71
|
/** Plural table names: user → users. Default: false */
|
|
70
72
|
usePlural?: boolean;
|
|
71
73
|
/** Column/table name casing. Explicit value takes precedence over hub.db.casing. */
|
|
72
|
-
casing?:
|
|
74
|
+
casing?: Casing;
|
|
73
75
|
};
|
|
74
76
|
}
|
|
75
77
|
export interface AuthRuntimeConfig {
|
package/dist/runtime/config.js
CHANGED
|
@@ -6,6 +6,8 @@ export function defineClientAuth(config) {
|
|
|
6
6
|
return (baseURL) => {
|
|
7
7
|
const ctx = { siteUrl: baseURL };
|
|
8
8
|
const resolved = typeof config === "function" ? config(ctx) : config;
|
|
9
|
-
|
|
9
|
+
const { baseURL: configuredBaseURL, ...resolvedOptions } = resolved;
|
|
10
|
+
const clientOptions = { ...resolvedOptions, baseURL: configuredBaseURL ?? baseURL };
|
|
11
|
+
return createAuthClient(clientOptions);
|
|
10
12
|
};
|
|
11
13
|
}
|
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
export declare const paginationQuerySchema:
|
|
3
|
-
page: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
4
|
-
limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
5
|
-
search: z.ZodDefault<z.ZodString>;
|
|
6
|
-
}, z.core.$strip>;
|
|
2
|
+
export declare const paginationQuerySchema: any;
|
|
7
3
|
export type PaginationQuery = z.infer<typeof paginationQuerySchema>;
|
|
8
4
|
export declare function sanitizeSearchPattern(search: string): string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
const SQL_LIKE_ESCAPE_RE = /[%_\\]/g;
|
|
2
3
|
export const paginationQuerySchema = z.object({
|
|
3
4
|
page: z.coerce.number().int().min(1).default(1),
|
|
4
5
|
limit: z.coerce.number().int().min(1).max(100).default(20),
|
|
@@ -7,5 +8,5 @@ export const paginationQuerySchema = z.object({
|
|
|
7
8
|
export function sanitizeSearchPattern(search) {
|
|
8
9
|
if (!search)
|
|
9
10
|
return "";
|
|
10
|
-
return `%${search.replace(
|
|
11
|
+
return `%${search.replace(SQL_LIKE_ESCAPE_RE, "\\$&")}%`;
|
|
11
12
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createError, defineEventHandler, getRequestURL } from "h3";
|
|
2
|
-
import { getRouteRules } from "
|
|
2
|
+
import { getRouteRules } from "#imports";
|
|
3
3
|
import { matchesUser } from "../../utils/match-user.js";
|
|
4
4
|
import { getUserSession, requireUserSession } from "../utils/session.js";
|
|
5
5
|
export default defineEventHandler(async (event) => {
|
|
@@ -1,8 +1,19 @@
|
|
|
1
|
+
import type { BetterAuthOptions } from 'better-auth';
|
|
1
2
|
import type { H3Event } from 'h3';
|
|
2
|
-
import createServerAuth from '#auth/server';
|
|
3
3
|
import { betterAuth } from 'better-auth';
|
|
4
|
+
import createServerAuth from '#auth/server';
|
|
4
5
|
type AuthOptions = ReturnType<typeof createServerAuth>;
|
|
5
|
-
type
|
|
6
|
+
type UserAuthConfig = AuthOptions & {
|
|
7
|
+
trustedOrigins?: BetterAuthOptions['trustedOrigins'];
|
|
8
|
+
secondaryStorage?: BetterAuthOptions['secondaryStorage'];
|
|
9
|
+
};
|
|
10
|
+
type ResolvedAuthOptions = UserAuthConfig & {
|
|
11
|
+
secret: string;
|
|
12
|
+
baseURL: string;
|
|
13
|
+
trustedOrigins?: BetterAuthOptions['trustedOrigins'];
|
|
14
|
+
database?: BetterAuthOptions['database'];
|
|
15
|
+
};
|
|
16
|
+
type AuthInstance = ReturnType<typeof betterAuth<ResolvedAuthOptions>>;
|
|
6
17
|
/** Returns Better Auth instance. Caches per resolved host (or single instance when siteUrl is explicit). */
|
|
7
18
|
export declare function serverAuth(event?: H3Event): AuthInstance;
|
|
8
19
|
export {};
|
|
@@ -1,14 +1,27 @@
|
|
|
1
|
-
import { createDatabase, db } from "#auth/database";
|
|
2
|
-
import { createSecondaryStorage } from "#auth/secondary-storage";
|
|
3
|
-
import createServerAuth from "#auth/server";
|
|
4
1
|
import { betterAuth } from "better-auth";
|
|
5
2
|
import { getRequestHost, getRequestProtocol } from "h3";
|
|
6
3
|
import { useRuntimeConfig } from "nitropack/runtime";
|
|
7
4
|
import { withoutProtocol } from "ufo";
|
|
5
|
+
import { createDatabase, db } from "#auth/database";
|
|
6
|
+
import { createSecondaryStorage } from "#auth/secondary-storage";
|
|
7
|
+
import createServerAuth from "#auth/server";
|
|
8
8
|
import { resolveCustomSecondaryStorageRequirement } from "./custom-secondary-storage.js";
|
|
9
9
|
const _authCache = /* @__PURE__ */ new Map();
|
|
10
|
+
const requestAuthKey = Symbol.for("nuxt-better-auth.requestAuth");
|
|
10
11
|
let _baseURLInferenceLogged = false;
|
|
11
12
|
let _customSecondaryStorageMisconfigWarned = false;
|
|
13
|
+
const fallbackRequestAuthContext = /* @__PURE__ */ new WeakMap();
|
|
14
|
+
function getRequestAuthContext(event) {
|
|
15
|
+
const eventWithContext = event;
|
|
16
|
+
if (eventWithContext.context && typeof eventWithContext.context === "object")
|
|
17
|
+
return eventWithContext.context;
|
|
18
|
+
let context = fallbackRequestAuthContext.get(event);
|
|
19
|
+
if (!context) {
|
|
20
|
+
context = {};
|
|
21
|
+
fallbackRequestAuthContext.set(event, context);
|
|
22
|
+
}
|
|
23
|
+
return context;
|
|
24
|
+
}
|
|
12
25
|
function normalizeLoopbackOrigin(origin) {
|
|
13
26
|
if (!import.meta.dev)
|
|
14
27
|
return origin;
|
|
@@ -155,8 +168,8 @@ function getRequestOrigin(request) {
|
|
|
155
168
|
return void 0;
|
|
156
169
|
}
|
|
157
170
|
}
|
|
158
|
-
function withDevTrustedOrigins(trustedOrigins
|
|
159
|
-
if (!import.meta.dev
|
|
171
|
+
function withDevTrustedOrigins(trustedOrigins) {
|
|
172
|
+
if (!import.meta.dev)
|
|
160
173
|
return trustedOrigins;
|
|
161
174
|
const devOrigins = getDevTrustedOrigins();
|
|
162
175
|
const mergeOrigins = (origins, request) => {
|
|
@@ -183,14 +196,15 @@ function withDevTrustedOrigins(trustedOrigins, hasExplicitSiteUrl) {
|
|
|
183
196
|
export function serverAuth(event) {
|
|
184
197
|
const runtimeConfig = useRuntimeConfig();
|
|
185
198
|
const siteUrl = getBaseURL(event);
|
|
199
|
+
const requestOrigin = resolveEventOrigin(event);
|
|
186
200
|
const hasExplicitSiteUrl = runtimeConfig.public.siteUrl && typeof runtimeConfig.public.siteUrl === "string";
|
|
187
201
|
const cacheKey = hasExplicitSiteUrl ? "__explicit__" : siteUrl;
|
|
188
|
-
const
|
|
189
|
-
if (
|
|
190
|
-
return
|
|
191
|
-
const database = createDatabase();
|
|
192
|
-
const userConfig = createServerAuth({ runtimeConfig, db });
|
|
193
|
-
const trustedOrigins = withDevTrustedOrigins(userConfig.trustedOrigins
|
|
202
|
+
const requestContext = event ? getRequestAuthContext(event) : void 0;
|
|
203
|
+
if (requestContext?.[requestAuthKey])
|
|
204
|
+
return requestContext[requestAuthKey];
|
|
205
|
+
const database = createDatabase(event);
|
|
206
|
+
const userConfig = createServerAuth({ runtimeConfig, db, requestOrigin });
|
|
207
|
+
const trustedOrigins = withDevTrustedOrigins(userConfig.trustedOrigins);
|
|
194
208
|
const hubSecondaryStorage = runtimeConfig.auth?.hubSecondaryStorage;
|
|
195
209
|
const customSecondaryStorage = resolveCustomSecondaryStorageRequirement(hubSecondaryStorage, userConfig.secondaryStorage != null, Boolean(import.meta.dev));
|
|
196
210
|
if (customSecondaryStorage?.shouldThrow)
|
|
@@ -199,14 +213,26 @@ export function serverAuth(event) {
|
|
|
199
213
|
_customSecondaryStorageMisconfigWarned = true;
|
|
200
214
|
console.warn(customSecondaryStorage.message);
|
|
201
215
|
}
|
|
202
|
-
|
|
216
|
+
if (!database) {
|
|
217
|
+
const cached = _authCache.get(cacheKey);
|
|
218
|
+
if (cached) {
|
|
219
|
+
if (requestContext)
|
|
220
|
+
requestContext[requestAuthKey] = cached;
|
|
221
|
+
return cached;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
const authOptions = {
|
|
203
225
|
...userConfig,
|
|
204
|
-
...database
|
|
205
|
-
...hubSecondaryStorage === true
|
|
226
|
+
...database ? { database } : {},
|
|
227
|
+
...hubSecondaryStorage === true ? { secondaryStorage: createSecondaryStorage() } : {},
|
|
206
228
|
secret: runtimeConfig.betterAuthSecret,
|
|
207
229
|
baseURL: siteUrl,
|
|
208
230
|
trustedOrigins
|
|
209
|
-
}
|
|
210
|
-
|
|
231
|
+
};
|
|
232
|
+
const auth = betterAuth(authOptions);
|
|
233
|
+
if (requestContext)
|
|
234
|
+
requestContext[requestAuthKey] = auth;
|
|
235
|
+
if (!database)
|
|
236
|
+
_authCache.set(cacheKey, auth);
|
|
211
237
|
return auth;
|
|
212
238
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import type { AppSession, RequireSessionOptions } from '#nuxt-better-auth';
|
|
2
1
|
import type { H3Event } from 'h3';
|
|
2
|
+
import type { AppSession, AuthSession, RequireSessionOptions } from '#nuxt-better-auth';
|
|
3
3
|
export declare function getRequestSession(event: H3Event): Promise<AppSession | null>;
|
|
4
4
|
export declare function getUserSession(event: H3Event): Promise<AppSession | null>;
|
|
5
|
+
export declare function setSessionCookie(event: H3Event, token: string): Promise<void>;
|
|
6
|
+
export declare function createSession(event: H3Event, userId: string): Promise<AuthSession>;
|
|
5
7
|
export declare function requireUserSession(event: H3Event, options?: RequireSessionOptions): Promise<AppSession>;
|