@nuxtjs/better-auth 0.3.11 → 0.3.13
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.json +1 -1
- package/dist/module.mjs +61 -6
- package/dist/runtime/app/middleware/auth.global.js +1 -1
- package/dist/runtime/internal/auth-route-rules.d.ts +2 -2
- package/dist/runtime/internal/auth-route-rules.js +6 -5
- package/dist/runtime/server/internal/nitro2.d.ts +12 -2
- package/dist/runtime/server/internal/nitro2.js +118 -18
- package/dist/runtime/server/internal/portable.js +1 -1
- package/dist/runtime/server/middleware/route-access.js +20 -1
- package/dist/runtime/server/utils/auth.js +15 -2
- package/package.json +21 -15
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { mkdir, writeFile } from 'node:fs/promises';
|
|
3
|
-
import { getLayerDirectories, resolveServerVariant, hasNuxtCompatibility, hasNuxtModuleCompatibility, updateTemplates, addServerImports, addServerHandler, addNitroPlugin, addImports, addPlugin, addComponentsDir, addRouteMiddleware, extendPages, addTemplate, hasNuxtModule,
|
|
3
|
+
import { getLayerDirectories, resolveServerVariant, hasNuxtCompatibility, hasNuxtModuleCompatibility, addTypeTemplate, updateTemplates, addServerImports, addServerHandler, addNitroPlugin, addImports, addPlugin, addComponentsDir, addRouteMiddleware, extendPages, addTemplate, hasNuxtModule, defineNuxtModule, createResolver, getNitroVersion } from '@nuxt/kit';
|
|
4
4
|
import { consola as consola$1 } from 'consola';
|
|
5
5
|
import { defineDiagnostics, Diagnostic, formatDiagnostic } from 'nostics';
|
|
6
6
|
import { isAbsolute, join, resolve, relative, dirname } from 'pathe';
|
|
@@ -13,7 +13,7 @@ import { isCI, isTest } from 'std-env';
|
|
|
13
13
|
import { isInternalAssetPath } from '../dist/runtime/internal/auth-route-rules.js';
|
|
14
14
|
export { defineClientAuth, defineServerAuth } from '../dist/runtime/config.js';
|
|
15
15
|
|
|
16
|
-
const version = "0.3.
|
|
16
|
+
const version = "0.3.13";
|
|
17
17
|
|
|
18
18
|
const CONFIG_EXTENSIONS = [".ts", ".js", ".mts", ".cts", ".mjs", ".cjs"];
|
|
19
19
|
const CONFIG_EXTENSION_RE = /\.[cm]?[jt]s$/;
|
|
@@ -284,6 +284,14 @@ const diagnostics = defineDiagnostics({
|
|
|
284
284
|
why: (p) => `Failed to load auth config at ${p.configPath}: ${p.cause instanceof Error ? p.cause.message : String(p.cause)}`,
|
|
285
285
|
fix: "Check the config imports and required environment variables, then restart Nuxt to regenerate the schema."
|
|
286
286
|
},
|
|
287
|
+
NUXT_AUTH_CLI_MISSING: {
|
|
288
|
+
why: "NuxtHub schema generation needs the Better Auth CLI package (auth), which is not installed.",
|
|
289
|
+
fix: (p) => `Run ${p.command}. Keep auth on the same version as better-auth.`
|
|
290
|
+
},
|
|
291
|
+
NUXT_AUTH_CLI_VERSION_MISMATCH: {
|
|
292
|
+
why: (p) => `auth@${p.cliVersion} installs better-auth@${p.cliBetterAuthVersion}, but this app uses better-auth@${p.betterAuthVersion}. Two copies of Better Auth cause conflicting types.`,
|
|
293
|
+
fix: (p) => `Run ${p.command} so auth and better-auth use the same version.`
|
|
294
|
+
},
|
|
287
295
|
NUXT_AUTH_EMPTY_SCHEMA: {
|
|
288
296
|
why: (p) => `Schema generation returned empty result for ${p.dialect}`,
|
|
289
297
|
fix: "Check the Better Auth plugins and database options in defineServerAuth(), then regenerate the schema."
|
|
@@ -379,6 +387,14 @@ function registerAuthMiddleware(resolve) {
|
|
|
379
387
|
}
|
|
380
388
|
function registerPrepareTypesHook(input) {
|
|
381
389
|
const { nuxt, serverDir, hasHubDb, serverImportsTypesFile } = input;
|
|
390
|
+
addTypeTemplate({
|
|
391
|
+
filename: "types/auth-route-rules.d.ts",
|
|
392
|
+
getContents: () => `
|
|
393
|
+
declare module '#auth/route-rules' {
|
|
394
|
+
export const authRouteRules: Record<string, { auth?: unknown }>
|
|
395
|
+
}
|
|
396
|
+
`
|
|
397
|
+
}, { nitro: true, node: true });
|
|
382
398
|
nuxt.hook("prepare:types", ({ nodeTsConfig, nodeReferences, sharedReferences }) => {
|
|
383
399
|
nodeTsConfig.compilerOptions ||= {};
|
|
384
400
|
nodeTsConfig.compilerOptions.paths ||= {};
|
|
@@ -470,6 +486,40 @@ function registerRouteRulesMetaHook(nuxt) {
|
|
|
470
486
|
function dialectToProvider(dialect) {
|
|
471
487
|
return dialect === "postgresql" ? "pg" : dialect;
|
|
472
488
|
}
|
|
489
|
+
const EXACT_VERSION_RE = /^\d+\.\d+\.\d+(?:-[\w.]+)?$/;
|
|
490
|
+
const LOCKFILES = [["pnpm-lock.yaml", "pnpm"], ["yarn.lock", "yarn"], ["bun.lock", "bun"], ["bun.lockb", "bun"], ["package-lock.json", "npm"]];
|
|
491
|
+
function readInstalledPackage(name) {
|
|
492
|
+
let entry;
|
|
493
|
+
try {
|
|
494
|
+
entry = createRequire(import.meta.url).resolve(name === "auth" ? "auth/api" : name);
|
|
495
|
+
} catch {
|
|
496
|
+
return void 0;
|
|
497
|
+
}
|
|
498
|
+
for (let dir = dirname(entry); dir !== dirname(dir); dir = dirname(dir)) {
|
|
499
|
+
const file = join(dir, "package.json");
|
|
500
|
+
if (!existsSync(file))
|
|
501
|
+
continue;
|
|
502
|
+
const pkg = JSON.parse(readFileSync(file, "utf8"));
|
|
503
|
+
if (pkg.name === name)
|
|
504
|
+
return pkg;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
function devInstallCommand(spec, rootDir) {
|
|
508
|
+
const agent = process.env.npm_config_user_agent?.split("/")[0];
|
|
509
|
+
const manager = LOCKFILES.find(([file]) => existsSync(join(rootDir, file)))?.[1] ?? LOCKFILES.find(([, name]) => name === agent)?.[1] ?? "npm";
|
|
510
|
+
return manager === "npm" ? `npm install -D ${spec}` : `${manager} add -D ${spec}`;
|
|
511
|
+
}
|
|
512
|
+
function checkBetterAuthCli(rootDir, readPackage = readInstalledPackage) {
|
|
513
|
+
const betterAuthVersion = readPackage("better-auth")?.version;
|
|
514
|
+
const spec = betterAuthVersion ? `auth@${betterAuthVersion}` : "auth";
|
|
515
|
+
const cli = readPackage("auth");
|
|
516
|
+
if (!cli)
|
|
517
|
+
return { error: diagnostics.NUXT_AUTH_CLI_MISSING({ command: devInstallCommand(spec, rootDir) }) };
|
|
518
|
+
const cliBetterAuthVersion = cli.dependencies?.["better-auth"];
|
|
519
|
+
if (betterAuthVersion && cliBetterAuthVersion && EXACT_VERSION_RE.test(cliBetterAuthVersion) && cliBetterAuthVersion !== betterAuthVersion)
|
|
520
|
+
return { warn: diagnostics.NUXT_AUTH_CLI_VERSION_MISMATCH({ cliVersion: cli.version ?? cliBetterAuthVersion, cliBetterAuthVersion, betterAuthVersion, command: devInstallCommand(spec, rootDir) }) };
|
|
521
|
+
return {};
|
|
522
|
+
}
|
|
473
523
|
async function generateDrizzleSchema(authOptions, dialect, schemaOptions) {
|
|
474
524
|
const { generateDrizzleSchema: generateDrizzleSchema2 } = await import('auth/api');
|
|
475
525
|
const provider = dialectToProvider(dialect);
|
|
@@ -631,6 +681,11 @@ async function setupBetterAuthSchema(nuxt, serverConfigPath, options, consola, h
|
|
|
631
681
|
consola.warn(formatDiagnostic(diagnostics.NUXT_AUTH_UNSUPPORTED_DIALECT({ dialect })));
|
|
632
682
|
return;
|
|
633
683
|
}
|
|
684
|
+
const cli = checkBetterAuthCli(nuxt.options.rootDir);
|
|
685
|
+
if (cli.error)
|
|
686
|
+
throw cli.error;
|
|
687
|
+
if (cli.warn)
|
|
688
|
+
consola.warn(formatDiagnostic(cli.warn));
|
|
634
689
|
const context = { nuxt, serverConfigPath };
|
|
635
690
|
try {
|
|
636
691
|
const authConfig = await loadAuthOptions(context);
|
|
@@ -1092,10 +1147,10 @@ function getRuntimeRouteRules(nuxt) {
|
|
|
1092
1147
|
}
|
|
1093
1148
|
function registerAuthRouteRulesValidation(nuxt) {
|
|
1094
1149
|
nuxt.hook("nitro:init", (nitro) => {
|
|
1095
|
-
assertSafeAuthRouteRules(nitro.options.routeRules);
|
|
1150
|
+
assertSafeAuthRouteRules(nitro.options.routeRules, nuxt.options.app.baseURL);
|
|
1096
1151
|
});
|
|
1097
1152
|
}
|
|
1098
|
-
function assertSafeAuthRouteRules(routeRules) {
|
|
1153
|
+
function assertSafeAuthRouteRules(routeRules, baseURL = "/") {
|
|
1099
1154
|
if (!Object.keys(routeRules).length)
|
|
1100
1155
|
return;
|
|
1101
1156
|
const matcher = toRouteMatcher(createRouter({ routes: routeRules }));
|
|
@@ -1104,7 +1159,7 @@ function assertSafeAuthRouteRules(routeRules) {
|
|
|
1104
1159
|
for (const path of collectRouteRulePaths(patterns, ""))
|
|
1105
1160
|
paths.add(path);
|
|
1106
1161
|
const conflicts = [...paths].flatMap((path) => {
|
|
1107
|
-
if (isInternalAssetPath(path))
|
|
1162
|
+
if (isInternalAssetPath(path, baseURL))
|
|
1108
1163
|
return [];
|
|
1109
1164
|
const matches = matcher.matchAll(path);
|
|
1110
1165
|
const effectiveRule = defu({}, ...matches.reverse());
|
|
@@ -1861,7 +1916,7 @@ const module$1 = defineNuxtModule({
|
|
|
1861
1916
|
const finishSetupOnce = () => {
|
|
1862
1917
|
setupPromise ||= finishSetup().catch((error) => {
|
|
1863
1918
|
if (error instanceof Diagnostic)
|
|
1864
|
-
throw new
|
|
1919
|
+
throw new TypeError(formatDiagnostic(error), { cause: error });
|
|
1865
1920
|
throw error;
|
|
1866
1921
|
});
|
|
1867
1922
|
return setupPromise;
|
|
@@ -10,7 +10,7 @@ let routeRulesMatcherPromise = null;
|
|
|
10
10
|
export default defineNuxtRouteMiddleware(async (to) => {
|
|
11
11
|
const runtimeConfig = useRuntimeConfig();
|
|
12
12
|
const path = normalizeAuthRoutePath(to.path, runtimeConfig.app?.baseURL);
|
|
13
|
-
if (shouldSkipAuthRouteRules(to.path) || shouldSkipAuthRouteRules(path))
|
|
13
|
+
if (shouldSkipAuthRouteRules(to.path, runtimeConfig.app?.baseURL) || shouldSkipAuthRouteRules(path, runtimeConfig.app?.baseURL))
|
|
14
14
|
return;
|
|
15
15
|
if (to.matched?.length === 0)
|
|
16
16
|
return;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AuthRouteRules } from '../types.js';
|
|
2
|
-
export declare function isInternalAssetPath(path: string): boolean;
|
|
2
|
+
export declare function isInternalAssetPath(path: string, baseURL?: string): boolean;
|
|
3
3
|
export declare function normalizeAuthRoutePath(path: string, baseURL?: string): string;
|
|
4
4
|
export declare function normalizeAuthRouteRule(rule: unknown): AuthRouteRules['auth'];
|
|
5
|
-
export declare function shouldSkipAuthRouteRules(path: string): boolean;
|
|
5
|
+
export declare function shouldSkipAuthRouteRules(path: string, baseURL?: string): boolean;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { withoutBase } from "ufo";
|
|
2
|
-
const internalAssetPaths = ["/_fonts", "/_ipx", "/_nuxt", "/api/_nuxt_icon"];
|
|
3
|
-
export function isInternalAssetPath(path) {
|
|
2
|
+
const internalAssetPaths = ["/_fonts", "/_ipx", "/_nuxt", "/_scripts/assets", "/api/_nuxt_icon"];
|
|
3
|
+
export function isInternalAssetPath(path, baseURL = "/") {
|
|
4
4
|
const pathname = path.split(/[?#]/, 1)[0] || "/";
|
|
5
|
+
const normalizedPathname = withoutBase(pathname, baseURL) || "/";
|
|
5
6
|
return internalAssetPaths.some((prefix) => {
|
|
6
|
-
return
|
|
7
|
+
return normalizedPathname === prefix || normalizedPathname.startsWith(`${prefix}/`);
|
|
7
8
|
});
|
|
8
9
|
}
|
|
9
10
|
const internalRouteRuleAuthPaths = /* @__PURE__ */ new Set([
|
|
@@ -29,7 +30,7 @@ export function normalizeAuthRouteRule(rule) {
|
|
|
29
30
|
return rule.options;
|
|
30
31
|
return rule;
|
|
31
32
|
}
|
|
32
|
-
export function shouldSkipAuthRouteRules(path) {
|
|
33
|
+
export function shouldSkipAuthRouteRules(path, baseURL = "/") {
|
|
33
34
|
const pathname = path.split(/[?#]/, 1)[0] || "/";
|
|
34
|
-
return isInternalAssetPath(pathname) || internalRouteRuleAuthPaths.has(pathname) || internalRouteRuleAuthPrefixes.some((prefix) => pathname.startsWith(prefix));
|
|
35
|
+
return isInternalAssetPath(pathname, baseURL) || internalRouteRuleAuthPaths.has(pathname) || internalRouteRuleAuthPrefixes.some((prefix) => pathname.startsWith(prefix));
|
|
35
36
|
}
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import type { H3Event } from 'h3';
|
|
2
2
|
import type { AuthRouteRules } from '../../types.js';
|
|
3
|
-
import { defineEventHandler
|
|
3
|
+
import { defineEventHandler } from 'h3';
|
|
4
4
|
import { useRuntimeConfig } from 'nitropack/runtime';
|
|
5
|
-
export { defineEventHandler,
|
|
5
|
+
export { defineEventHandler, useRuntimeConfig, };
|
|
6
6
|
export type ServerEvent = H3Event;
|
|
7
|
+
export declare function getRequestHost(event: ServerEvent, options?: {
|
|
8
|
+
xForwardedHost?: boolean;
|
|
9
|
+
}): string;
|
|
10
|
+
export declare function getRequestProtocol(event: ServerEvent, options?: {
|
|
11
|
+
xForwardedProto?: boolean;
|
|
12
|
+
}): string;
|
|
13
|
+
export declare function getRequestURL(event: ServerEvent): URL;
|
|
14
|
+
export declare function getQuery(event: ServerEvent): Record<string, string | string[]>;
|
|
15
|
+
export declare function toWebRequest(event: ServerEvent): Request;
|
|
16
|
+
export declare function readBody(event: ServerEvent): Promise<unknown>;
|
|
7
17
|
export declare function splitCookiesString(cookiesString: string | string[]): string[];
|
|
8
18
|
export declare function getAuthRouteRules(event: ServerEvent): AuthRouteRules;
|
|
9
19
|
export declare function createAuthError(status: number, statusText: string): Error;
|
|
@@ -1,31 +1,131 @@
|
|
|
1
1
|
import { splitSetCookieString } from "cookie-es";
|
|
2
|
-
import {
|
|
3
|
-
createError,
|
|
4
|
-
defineEventHandler,
|
|
5
|
-
getQuery,
|
|
6
|
-
getRequestHost,
|
|
7
|
-
getRequestProtocol,
|
|
8
|
-
getRequestURL,
|
|
9
|
-
readBody,
|
|
10
|
-
toWebRequest
|
|
11
|
-
} from "h3";
|
|
2
|
+
import { defineEventHandler } from "h3";
|
|
12
3
|
import { getRouteRules, useRuntimeConfig } from "nitropack/runtime";
|
|
13
4
|
export {
|
|
14
5
|
defineEventHandler,
|
|
15
|
-
getQuery,
|
|
16
|
-
getRequestHost,
|
|
17
|
-
getRequestProtocol,
|
|
18
|
-
getRequestURL,
|
|
19
|
-
readBody,
|
|
20
|
-
toWebRequest,
|
|
21
6
|
useRuntimeConfig
|
|
22
7
|
};
|
|
8
|
+
function createNitro2AuthError(status, statusText) {
|
|
9
|
+
const error = new Error(statusText);
|
|
10
|
+
const markerConstructor = function Nitro2ErrorConstructor() {
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(markerConstructor, "__h3_error__", { value: true });
|
|
13
|
+
Object.defineProperties(error, {
|
|
14
|
+
name: { value: "HTTPError", configurable: true, enumerable: false, writable: true },
|
|
15
|
+
constructor: { value: markerConstructor, configurable: true },
|
|
16
|
+
__h3_error__: { value: true, configurable: true, enumerable: true, writable: true },
|
|
17
|
+
status: { value: status, configurable: true, enumerable: true, writable: true },
|
|
18
|
+
statusText: { value: statusText, configurable: true, enumerable: true, writable: true },
|
|
19
|
+
statusCode: { value: status, configurable: true, enumerable: true, writable: true },
|
|
20
|
+
statusMessage: { value: statusText, configurable: true, enumerable: true, writable: true },
|
|
21
|
+
toJSON: {
|
|
22
|
+
value: () => ({
|
|
23
|
+
status,
|
|
24
|
+
statusText,
|
|
25
|
+
statusCode: status,
|
|
26
|
+
statusMessage: statusText,
|
|
27
|
+
message: statusText,
|
|
28
|
+
unhandled: false,
|
|
29
|
+
fatal: false
|
|
30
|
+
}),
|
|
31
|
+
configurable: true
|
|
32
|
+
},
|
|
33
|
+
unhandled: { value: false, configurable: true, enumerable: true, writable: true },
|
|
34
|
+
fatal: { value: false, configurable: true, enumerable: true, writable: true }
|
|
35
|
+
});
|
|
36
|
+
return error;
|
|
37
|
+
}
|
|
38
|
+
function requestHeaders(event) {
|
|
39
|
+
return event.node?.req?.headers ?? {};
|
|
40
|
+
}
|
|
41
|
+
export function getRequestHost(event, options = {}) {
|
|
42
|
+
const headers = requestHeaders(event);
|
|
43
|
+
if (options.xForwardedHost) {
|
|
44
|
+
const forwarded = headers["x-forwarded-host"];
|
|
45
|
+
const host2 = Array.isArray(forwarded) ? forwarded[0] : forwarded?.split(",")[0]?.trim();
|
|
46
|
+
if (host2)
|
|
47
|
+
return host2;
|
|
48
|
+
}
|
|
49
|
+
const host = headers.host;
|
|
50
|
+
return (Array.isArray(host) ? host[0] : host) || "localhost";
|
|
51
|
+
}
|
|
52
|
+
export function getRequestProtocol(event, options = {}) {
|
|
53
|
+
const headers = requestHeaders(event);
|
|
54
|
+
if (options.xForwardedProto !== false && headers["x-forwarded-proto"] === "https")
|
|
55
|
+
return "https";
|
|
56
|
+
return event.node?.req?.socket && event.node.req.socket["encrypted"] ? "https" : "http";
|
|
57
|
+
}
|
|
58
|
+
export function getRequestURL(event) {
|
|
59
|
+
const req = event.node?.req ?? {};
|
|
60
|
+
const path = req.originalUrl || req.url || event.path || "/";
|
|
61
|
+
return new URL(path, `${getRequestProtocol(event)}://${getRequestHost(event)}`);
|
|
62
|
+
}
|
|
63
|
+
export function getQuery(event) {
|
|
64
|
+
const query = {};
|
|
65
|
+
for (const [key, value] of getRequestURL(event).searchParams) {
|
|
66
|
+
const previous = query[key];
|
|
67
|
+
query[key] = previous === void 0 ? value : Array.isArray(previous) ? [...previous, value] : [previous, value];
|
|
68
|
+
}
|
|
69
|
+
return query;
|
|
70
|
+
}
|
|
71
|
+
export function toWebRequest(event) {
|
|
72
|
+
const req = event.node?.req;
|
|
73
|
+
const webRequest = event.web?.request;
|
|
74
|
+
if (webRequest)
|
|
75
|
+
return webRequest;
|
|
76
|
+
const init = {
|
|
77
|
+
method: req?.method,
|
|
78
|
+
headers: req?.headers ? Object.fromEntries(Object.entries(req.headers).flatMap(([key, value]) => value === void 0 ? [] : [[key, Array.isArray(value) ? value.join(", ") : value]])) : void 0,
|
|
79
|
+
duplex: "half"
|
|
80
|
+
};
|
|
81
|
+
if (req && req.method !== "GET" && req.method !== "HEAD")
|
|
82
|
+
init.body = requestBody(req);
|
|
83
|
+
return new Request(getRequestURL(event), init);
|
|
84
|
+
}
|
|
85
|
+
const h3RawBody = Symbol.for("h3RawBody");
|
|
86
|
+
function requestBody(req) {
|
|
87
|
+
const rawBody = req[h3RawBody];
|
|
88
|
+
if (rawBody) {
|
|
89
|
+
return new ReadableStream({
|
|
90
|
+
async start(controller) {
|
|
91
|
+
const bytes = await rawBody;
|
|
92
|
+
if (bytes?.length)
|
|
93
|
+
controller.enqueue(bytes);
|
|
94
|
+
controller.close();
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
const body = req.rawBody ?? req.body;
|
|
99
|
+
if (body === void 0 || body === null)
|
|
100
|
+
return "__unenv__" in req ? void 0 : req;
|
|
101
|
+
if (body.constructor === Object)
|
|
102
|
+
return JSON.stringify(body);
|
|
103
|
+
return body;
|
|
104
|
+
}
|
|
105
|
+
export async function readBody(event) {
|
|
106
|
+
const request = toWebRequest(event);
|
|
107
|
+
const contentType = request.headers.get("content-type") || "";
|
|
108
|
+
if (contentType.includes("application/json"))
|
|
109
|
+
return request.json();
|
|
110
|
+
if (contentType.includes("application/x-www-form-urlencoded"))
|
|
111
|
+
return Object.fromEntries((await request.text()).split("&").filter(Boolean).map((pair) => pair.split("=").map(decodeURIComponent)));
|
|
112
|
+
return request.text();
|
|
113
|
+
}
|
|
23
114
|
export function splitCookiesString(cookiesString) {
|
|
24
115
|
return splitSetCookieString(cookiesString);
|
|
25
116
|
}
|
|
26
117
|
export function getAuthRouteRules(event) {
|
|
27
|
-
|
|
118
|
+
const eventWithContext = event;
|
|
119
|
+
if (!eventWithContext.context)
|
|
120
|
+
eventWithContext.context = {};
|
|
121
|
+
if (!eventWithContext.path)
|
|
122
|
+
eventWithContext.path = getRequestURL(event).pathname;
|
|
123
|
+
try {
|
|
124
|
+
return getRouteRules(event) || {};
|
|
125
|
+
} catch {
|
|
126
|
+
return {};
|
|
127
|
+
}
|
|
28
128
|
}
|
|
29
129
|
export function createAuthError(status, statusText) {
|
|
30
|
-
return
|
|
130
|
+
return createNitro2AuthError(status, statusText);
|
|
31
131
|
}
|
|
@@ -25,7 +25,7 @@ export function splitCookiesString(cookiesString) {
|
|
|
25
25
|
}
|
|
26
26
|
export function getAuthRouteRules(event) {
|
|
27
27
|
const rules = getRouteRules(event);
|
|
28
|
-
return { auth: normalizeAuthRouteRule(rules
|
|
28
|
+
return { auth: normalizeAuthRouteRule(rules?.auth) };
|
|
29
29
|
}
|
|
30
30
|
export function createAuthError(status, statusText) {
|
|
31
31
|
return createError({ status, statusText });
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import { defu } from "defu";
|
|
2
|
+
import { createRouter, toRouteMatcher } from "radix3";
|
|
1
3
|
import { normalizeAuthRoutePath, shouldSkipAuthRouteRules } from "../../internal/auth-route-rules.js";
|
|
2
4
|
import { matchesUser } from "../../utils/match-user.js";
|
|
3
5
|
import { prepareAuthSecret } from "../internal/auth-secret.js";
|
|
4
6
|
import { createAuthError, defineEventHandler, getAuthRouteRules, getRequestURL, useRuntimeConfig } from "../internal/nitro-compat.js";
|
|
5
7
|
import { getUserSession, requireUserSession } from "../utils/session.js";
|
|
8
|
+
let authRouteRulesMatcherPromise = null;
|
|
6
9
|
export default defineEventHandler(async (event) => {
|
|
7
10
|
await prepareAuthSecret();
|
|
8
11
|
const path = normalizeAuthRoutePath(
|
|
@@ -13,7 +16,7 @@ export default defineEventHandler(async (event) => {
|
|
|
13
16
|
return;
|
|
14
17
|
if (shouldSkipAuthRouteRules(path))
|
|
15
18
|
return;
|
|
16
|
-
const rules =
|
|
19
|
+
const rules = await resolveAuthRouteRules(event, path);
|
|
17
20
|
if (!rules.auth)
|
|
18
21
|
return;
|
|
19
22
|
const auth = rules.auth;
|
|
@@ -32,3 +35,19 @@ export default defineEventHandler(async (event) => {
|
|
|
32
35
|
}
|
|
33
36
|
}
|
|
34
37
|
});
|
|
38
|
+
async function resolveAuthRouteRules(event, path) {
|
|
39
|
+
const rules = getAuthRouteRules(event);
|
|
40
|
+
if (rules?.auth !== void 0)
|
|
41
|
+
return rules;
|
|
42
|
+
if (!authRouteRulesMatcherPromise) {
|
|
43
|
+
authRouteRulesMatcherPromise = import("#auth/route-rules").then((mod) => {
|
|
44
|
+
const routeRules = mod.authRouteRules || {};
|
|
45
|
+
return Object.keys(routeRules).length ? toRouteMatcher(createRouter({ routes: routeRules })) : null;
|
|
46
|
+
}).catch(() => null);
|
|
47
|
+
}
|
|
48
|
+
const matcher = await authRouteRulesMatcherPromise;
|
|
49
|
+
const matches = matcher?.matchAll(path);
|
|
50
|
+
if (!matches?.length)
|
|
51
|
+
return rules || {};
|
|
52
|
+
return defu({}, ...matches.reverse());
|
|
53
|
+
}
|
|
@@ -67,8 +67,21 @@ function resolveConfiguredSiteUrl(config) {
|
|
|
67
67
|
function resolveEventOrigin(event) {
|
|
68
68
|
if (!event)
|
|
69
69
|
return void 0;
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
let host;
|
|
71
|
+
let protocol;
|
|
72
|
+
try {
|
|
73
|
+
host = getRequestHost(event, { xForwardedHost: true });
|
|
74
|
+
protocol = getRequestProtocol(event, { xForwardedProto: true });
|
|
75
|
+
} catch {
|
|
76
|
+
const request = event.node?.req;
|
|
77
|
+
const headers = request?.headers ?? {};
|
|
78
|
+
const forwardedHost = headers["x-forwarded-host"];
|
|
79
|
+
const forwarded = Array.isArray(forwardedHost) ? forwardedHost[0] : forwardedHost?.split(",")[0]?.trim();
|
|
80
|
+
const rawHost = forwarded || headers.host;
|
|
81
|
+
host = (Array.isArray(rawHost) ? rawHost[0] : rawHost) || "";
|
|
82
|
+
const forwardedProto = headers["x-forwarded-proto"];
|
|
83
|
+
protocol = (Array.isArray(forwardedProto) ? forwardedProto[0] : forwardedProto) || (request?.socket?.encrypted ? "https" : "http");
|
|
84
|
+
}
|
|
72
85
|
if (!host || !protocol)
|
|
73
86
|
return void 0;
|
|
74
87
|
try {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuxtjs/better-auth",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.13",
|
|
5
5
|
"description": "Nuxt module for Better Auth integration with NuxtHub, route protection, session management, and role-based access",
|
|
6
6
|
"author": "onmax",
|
|
7
7
|
"license": "MIT",
|
|
@@ -61,6 +61,7 @@
|
|
|
61
61
|
"peerDependencies": {
|
|
62
62
|
"@nuxt/test-utils": "^4.1.0",
|
|
63
63
|
"@nuxthub/core": ">=0.10.5",
|
|
64
|
+
"auth": "1.7.12",
|
|
64
65
|
"better-auth": ">=1.7.3 <2"
|
|
65
66
|
},
|
|
66
67
|
"peerDependenciesMeta": {
|
|
@@ -69,18 +70,20 @@
|
|
|
69
70
|
},
|
|
70
71
|
"@nuxthub/core": {
|
|
71
72
|
"optional": true
|
|
73
|
+
},
|
|
74
|
+
"auth": {
|
|
75
|
+
"optional": true
|
|
72
76
|
}
|
|
73
77
|
},
|
|
74
78
|
"dependencies": {
|
|
75
79
|
"@nuxt/devtools-kit": "^3.4.1",
|
|
76
80
|
"@nuxt/kit": "^4.6.0",
|
|
77
81
|
"@types/node": "^24.13.3",
|
|
78
|
-
"auth": "1.7.7",
|
|
79
82
|
"consola": "^3.4.2",
|
|
80
83
|
"cookie-es": "^3.1.1",
|
|
81
84
|
"defu": "^6.1.7",
|
|
82
85
|
"get-port-please": "^3.2.0",
|
|
83
|
-
"h3": "^
|
|
86
|
+
"h3": "^2.0.0",
|
|
84
87
|
"jiti": "^2.7.0",
|
|
85
88
|
"nostics": "^1.2.0",
|
|
86
89
|
"pathe": "^2.0.3",
|
|
@@ -90,37 +93,40 @@
|
|
|
90
93
|
"zod": "^4.4.3"
|
|
91
94
|
},
|
|
92
95
|
"devDependencies": {
|
|
93
|
-
"@antfu/eslint-config": "^
|
|
96
|
+
"@antfu/eslint-config": "^10.0.0",
|
|
94
97
|
"@libsql/client": "^0.18.0",
|
|
95
98
|
"@libsql/linux-x64-gnu": "0.5.29",
|
|
96
99
|
"@nuxt/devtools": "^3.4.1",
|
|
97
|
-
"@nuxt/fonts": "1.0
|
|
100
|
+
"@nuxt/fonts": "1.2.0",
|
|
98
101
|
"@nuxt/module-builder": "^1.0.3",
|
|
99
102
|
"@nuxt/schema": "^4.6.0",
|
|
100
103
|
"@nuxt/test-utils": "^4.3.3",
|
|
101
104
|
"@nuxthub/core": "^0.10.8",
|
|
102
105
|
"@pinia/nuxt": "^1.0.2",
|
|
103
106
|
"@types/better-sqlite3": "^9.6.0",
|
|
107
|
+
"@typescript/typescript6": "6.0.2",
|
|
104
108
|
"@vue/test-utils": "^2.4.6",
|
|
105
|
-
"
|
|
106
|
-
"better-
|
|
109
|
+
"auth": "1.7.12",
|
|
110
|
+
"better-auth": "1.7.12",
|
|
111
|
+
"better-call": "1.4.4",
|
|
107
112
|
"better-sqlite3": "^13.0.0",
|
|
108
113
|
"drizzle-kit": "^0.31.10",
|
|
109
114
|
"drizzle-orm": "^0.45.2",
|
|
110
115
|
"eslint": "^10.8.1",
|
|
111
116
|
"happy-dom": "^21.0.0",
|
|
112
|
-
"nitropack": "2.13.
|
|
117
|
+
"nitropack": "2.13.5",
|
|
113
118
|
"nuxt": "^4.6.0",
|
|
114
119
|
"pinia": "^4.0.3",
|
|
115
|
-
"pkg-pr-new": "0.0.
|
|
120
|
+
"pkg-pr-new": "0.0.92",
|
|
116
121
|
"playwright-core": "1.64.1",
|
|
117
122
|
"postgres": "^3.4.9",
|
|
118
|
-
"typescript": "~
|
|
123
|
+
"typescript": "~7.0.0",
|
|
124
|
+
"typescript-next": "npm:typescript@~7.0.0",
|
|
119
125
|
"unstorage": "^1.17.5",
|
|
120
126
|
"vitest": "^5.0.0",
|
|
121
127
|
"vue": "3.5.44",
|
|
122
128
|
"vue-tsc": "^3.3.10",
|
|
123
|
-
"wrangler": "4.
|
|
129
|
+
"wrangler": "4.152.0",
|
|
124
130
|
"yaml": "^2.9.0"
|
|
125
131
|
},
|
|
126
132
|
"scripts": {
|
|
@@ -131,11 +137,11 @@
|
|
|
131
137
|
"dev:docs": "nuxi dev docs",
|
|
132
138
|
"build:docs": "nuxi build docs",
|
|
133
139
|
"deploy": "wrangler deploy",
|
|
134
|
-
"lint": "eslint .",
|
|
140
|
+
"lint": "NODE_OPTIONS='--import=./scripts/typescript6-shim.mjs --experimental-loader=./scripts/typescript6-shim.mjs' eslint .",
|
|
135
141
|
"lint:fix": "eslint . --fix",
|
|
136
|
-
"typecheck": "vue-tsc --noEmit",
|
|
137
|
-
"typecheck:runtime-server": "cd test/cases/plugins-type-inference && nuxi prepare && vue-tsc --noEmit --pretty false -p .nuxt/tsconfig.server.json",
|
|
138
|
-
"typecheck:playground": "pnpm -C playground exec nuxi prepare && pnpm -C playground exec vue-tsc --noEmit -p .nuxt/tsconfig.app.json",
|
|
142
|
+
"typecheck": "NODE_OPTIONS='--import=./scripts/typescript6-shim.mjs --experimental-loader=./scripts/typescript6-shim.mjs' vue-tsc --noEmit",
|
|
143
|
+
"typecheck:runtime-server": "cd test/cases/plugins-type-inference && NODE_OPTIONS='--import=../../../scripts/typescript6-shim.mjs --experimental-loader=../../../scripts/typescript6-shim.mjs' nuxi prepare && NODE_OPTIONS='--import=../../../scripts/typescript6-shim.mjs --experimental-loader=../../../scripts/typescript6-shim.mjs' vue-tsc --noEmit --pretty false -p .nuxt/tsconfig.server.json",
|
|
144
|
+
"typecheck:playground": "NODE_OPTIONS=\"--import=$PWD/scripts/typescript6-shim.mjs --experimental-loader=$PWD/scripts/typescript6-shim.mjs\" pnpm -C playground exec nuxi prepare && NODE_OPTIONS=\"--import=$PWD/scripts/typescript6-shim.mjs --experimental-loader=$PWD/scripts/typescript6-shim.mjs\" pnpm -C playground exec vue-tsc --noEmit -p .nuxt/tsconfig.app.json",
|
|
139
145
|
"test": "vitest run",
|
|
140
146
|
"test:watch": "vitest watch",
|
|
141
147
|
"test:runtime": "vitest run --config vitest.runtime.config.ts"
|