@nuxtjs/better-auth 0.3.14 → 0.3.16

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 CHANGED
@@ -1,5 +1,10 @@
1
1
  # `@nuxtjs/better-auth`
2
2
 
3
+ [![npm version](https://comark-ui.onmax.me/badge.svg?source=npm-version&package=%40nuxtjs%2Fbetter-auth&icon=npm)](https://www.npmjs.com/package/@nuxtjs/better-auth)
4
+ [![npm downloads](https://comark-ui.onmax.me/badge.svg?source=npm-downloads&package=%40nuxtjs%2Fbetter-auth&period=month&icon=npm)](https://www.npmjs.com/package/@nuxtjs/better-auth)
5
+ [![license](https://comark-ui.onmax.me/badge.svg?label=license&value=MIT)](https://github.com/nuxt-modules/better-auth/blob/main/LICENSE)
6
+ [![docs](https://comark-ui.onmax.me/badge.svg?label=docs&value=better-auth.nuxt.dev)](https://better-auth.nuxt.dev)
7
+
3
8
  Nuxt module for [Better Auth](https://better-auth.com) with Nuxt-native route protection, SSR-safe session access, auto-imported helpers, and optional NuxtHub-backed schema generation.
4
9
 
5
10
  ## Who this is for
package/dist/module.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuxtjs/better-auth",
3
- "version": "0.3.14",
3
+ "version": "0.3.16",
4
4
  "configKey": "auth",
5
5
  "compatibility": {
6
6
  "nuxt": ">=4.0.0"
package/dist/module.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { existsSync, readFileSync, statSync, writeFileSync } from 'node:fs';
2
- import { mkdir, writeFile } from 'node:fs/promises';
1
+ import { existsSync, readFileSync, statSync, readdirSync, writeFileSync } from 'node:fs';
2
+ import { readFile, mkdir, writeFile, rename, rm } from 'node:fs/promises';
3
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';
@@ -8,12 +8,12 @@ import { createRequire } from 'node:module';
8
8
  import { join as join$1 } from 'node:path';
9
9
  import { defu } from 'defu';
10
10
  import { toRouteMatcher, createRouter } from 'radix3';
11
- import { randomBytes } from 'node:crypto';
11
+ import { createHash, randomUUID, randomBytes } from 'node:crypto';
12
12
  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.14";
16
+ const version = "0.3.16";
17
17
 
18
18
  const CONFIG_EXTENSIONS = [".ts", ".js", ".mts", ".cts", ".mjs", ".cjs"];
19
19
  const CONFIG_EXTENSION_RE = /\.[cm]?[jt]s$/;
@@ -488,10 +488,10 @@ function dialectToProvider(dialect) {
488
488
  }
489
489
  const EXACT_VERSION_RE = /^\d+\.\d+\.\d+(?:-[\w.]+)?$/;
490
490
  const LOCKFILES = [["pnpm-lock.yaml", "pnpm"], ["yarn.lock", "yarn"], ["bun.lock", "bun"], ["bun.lockb", "bun"], ["package-lock.json", "npm"]];
491
- function readInstalledPackage(name) {
491
+ function findInstalledPackage(name, parent) {
492
492
  let entry;
493
493
  try {
494
- entry = createRequire(import.meta.url).resolve(name === "auth" ? "auth/api" : name);
494
+ entry = createRequire(parent).resolve(name === "auth" ? "auth/api" : name);
495
495
  } catch {
496
496
  return void 0;
497
497
  }
@@ -501,9 +501,12 @@ function readInstalledPackage(name) {
501
501
  continue;
502
502
  const pkg = JSON.parse(readFileSync(file, "utf8"));
503
503
  if (pkg.name === name)
504
- return pkg;
504
+ return { dir, pkg };
505
505
  }
506
506
  }
507
+ function readInstalledPackage(name) {
508
+ return findInstalledPackage(name, import.meta.url)?.pkg;
509
+ }
507
510
  function devInstallCommand(spec, rootDir) {
508
511
  const agent = process.env.npm_config_user_agent?.split("/")[0];
509
512
  const manager = LOCKFILES.find(([file]) => existsSync(join(rootDir, file)))?.[1] ?? LOCKFILES.find(([, name]) => name === agent)?.[1] ?? "npm";
@@ -520,8 +523,7 @@ function checkBetterAuthCli(rootDir, readPackage = readInstalledPackage) {
520
523
  return { warn: diagnostics.NUXT_AUTH_CLI_VERSION_MISMATCH({ cliVersion: cli.version ?? cliBetterAuthVersion, cliBetterAuthVersion, betterAuthVersion, command: devInstallCommand(spec, rootDir) }) };
521
524
  return {};
522
525
  }
523
- async function generateDrizzleSchema(authOptions, dialect, schemaOptions) {
524
- const { generateDrizzleSchema: generateDrizzleSchema2 } = await import('auth/api');
526
+ function resolveDrizzleSchemaInput(authOptions, dialect, schemaOptions) {
525
527
  const provider = dialectToProvider(dialect);
526
528
  const options = {
527
529
  ...authOptions,
@@ -542,6 +544,11 @@ async function generateDrizzleSchema(authOptions, dialect, schemaOptions) {
542
544
  adapterConfig: { usePlural: schemaOptions?.usePlural ?? false }
543
545
  }
544
546
  };
547
+ return { options, adapter };
548
+ }
549
+ async function generateDrizzleSchema(authOptions, dialect, schemaOptions) {
550
+ const { generateDrizzleSchema: generateDrizzleSchema2 } = await import('auth/api');
551
+ const { options, adapter } = resolveDrizzleSchemaInput(authOptions, dialect, schemaOptions);
545
552
  const result = await generateDrizzleSchema2({
546
553
  adapter,
547
554
  options
@@ -551,6 +558,94 @@ async function generateDrizzleSchema(authOptions, dialect, schemaOptions) {
551
558
  }
552
559
  return result.code;
553
560
  }
561
+ const SCHEMA_CACHE_REVISION = 1;
562
+ const SCHEMA_GENERATOR_PACKAGES = ["auth", "better-auth", "@better-auth/core", "prettier"];
563
+ function hashPackageContents(dir) {
564
+ const hash = createHash("sha256");
565
+ function visit(relativeDir) {
566
+ const entries = readdirSync(join(dir, relativeDir), { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
567
+ for (const entry of entries) {
568
+ if (entry.name === "node_modules" || entry.name === ".git")
569
+ continue;
570
+ const relativePath = join(relativeDir, entry.name);
571
+ if (entry.isDirectory()) {
572
+ visit(relativePath);
573
+ } else {
574
+ hash.update(relativePath).update("\0");
575
+ hash.update(createHash("sha256").update(readFileSync(join(dir, relativePath))).digest());
576
+ }
577
+ }
578
+ }
579
+ visit("");
580
+ return hash.digest("hex");
581
+ }
582
+ function getSchemaGeneratorIdentity() {
583
+ const authApi = createRequire(import.meta.url).resolve("auth/api");
584
+ const generatorHash = createHash("sha256").update(readFileSync(authApi)).digest("hex");
585
+ const packages = SCHEMA_GENERATOR_PACKAGES.map((name) => {
586
+ const installed = findInstalledPackage(name, authApi);
587
+ const contentHash = installed && (name === "better-auth" || name === "@better-auth/core") ? hashPackageContents(installed.dir) : "";
588
+ return `${name}@${installed?.pkg.version} ${installed?.dir} ${contentHash}`;
589
+ });
590
+ return [`revision ${SCHEMA_CACHE_REVISION}`, generatorHash, ...packages];
591
+ }
592
+ function tagSchemaValue(_key, value) {
593
+ switch (typeof value) {
594
+ case "string":
595
+ return `s:${value}`;
596
+ case "number":
597
+ return Number.isFinite(value) ? value : `n:${value}`;
598
+ case "bigint":
599
+ return `b:${value}`;
600
+ case "function":
601
+ return `f:${String(value)}`;
602
+ case "symbol":
603
+ return `y:${String(value)}`;
604
+ case "undefined":
605
+ return "u:";
606
+ default:
607
+ return value;
608
+ }
609
+ }
610
+ async function getDrizzleSchemaKey(authOptions, dialect, schemaOptions) {
611
+ const { getAuthTables } = await import('better-auth/db');
612
+ const { options, adapter } = resolveDrizzleSchemaInput(authOptions, dialect, schemaOptions);
613
+ try {
614
+ const input = JSON.stringify([getAuthTables(options), options.advanced?.database?.generateId, adapter.options, getSchemaGeneratorIdentity()], tagSchemaValue);
615
+ return createHash("sha256").update(input).digest("hex");
616
+ } catch {
617
+ return void 0;
618
+ }
619
+ }
620
+ async function readCachedSchema(cacheFile, key) {
621
+ try {
622
+ const entry = JSON.parse(await readFile(cacheFile, "utf8"));
623
+ return entry.key === key && typeof entry.code === "string" ? entry.code : void 0;
624
+ } catch {
625
+ return void 0;
626
+ }
627
+ }
628
+ async function writeCachedSchema(cacheFile, key, code) {
629
+ const tempFile = `${cacheFile}.${randomUUID()}.tmp`;
630
+ try {
631
+ await mkdir(dirname(cacheFile), { recursive: true });
632
+ await writeFile(tempFile, JSON.stringify({ key, code }));
633
+ await rename(tempFile, cacheFile);
634
+ } catch {
635
+ await rm(tempFile, { force: true }).catch(() => {
636
+ });
637
+ }
638
+ }
639
+ async function generateCachedDrizzleSchema(authOptions, dialect, schemaOptions, cacheFile) {
640
+ const key = await getDrizzleSchemaKey(authOptions, dialect, schemaOptions);
641
+ const cached = key && await readCachedSchema(cacheFile, key);
642
+ if (cached)
643
+ return cached;
644
+ const code = await generateDrizzleSchema(authOptions, dialect, schemaOptions);
645
+ if (key)
646
+ await writeCachedSchema(cacheFile, key, code);
647
+ return code;
648
+ }
554
649
  function loadLocalEnv(rootDir) {
555
650
  if (!rootDir)
556
651
  return;
@@ -713,7 +808,8 @@ async function setupBetterAuthSchema(nuxt, serverConfigPath, options, consola, h
713
808
  };
714
809
  const hubCasing = getHubCasing(hub);
715
810
  const schemaOptions = { ...options.schema, useUuid: userConfig.advanced?.database?.generateId === "uuid", casing: options.schema?.casing ?? hubCasing };
716
- const schemaCode = await generateDrizzleSchema(authOptions, dialect, schemaOptions);
811
+ const schemaCacheFile = join(nuxt.options.buildDir, "cache", "better-auth", `schema.${dialect}.json`);
812
+ const schemaCode = await generateCachedDrizzleSchema(authOptions, dialect, schemaOptions, schemaCacheFile);
717
813
  const { getAuthTables } = await import('better-auth/db');
718
814
  const { initGetModelName } = await import('better-auth/adapters');
719
815
  const authTables = getAuthTables(authOptions);
@@ -1,14 +1,16 @@
1
- declare var __VLS_1: {
2
- loggedIn: boolean;
3
- user: import("../../types.js").AuthUser | null;
4
- session: import("../../types.js").ClientAuthSession | 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;
1
+ declare const __VLS_template: () => {
2
+ __VLS_Slots: {
3
+ default?: (props: {
4
+ loggedIn: boolean;
5
+ user: import("../../types.js").AuthUser | null;
6
+ session: import("../../types.js").ClientAuthSession | null;
7
+ signOut: (options?: import("../composables/useUserSession.js").SignOutOptions) => Promise<void>;
8
+ }) => any;
9
+ } & {
10
+ placeholder?: (props: {}) => any;
11
+ };
11
12
  };
13
+ type __VLS_Slots = ReturnType<typeof __VLS_template>['__VLS_Slots'];
12
14
  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
15
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
14
16
  declare const _default: typeof __VLS_export;
@@ -1,14 +1,16 @@
1
- declare var __VLS_1: {
2
- loggedIn: boolean;
3
- user: import("../../types.js").AuthUser | null;
4
- session: import("../../types.js").ClientAuthSession | 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;
1
+ declare const __VLS_template: () => {
2
+ __VLS_Slots: {
3
+ default?: (props: {
4
+ loggedIn: boolean;
5
+ user: import("../../types.js").AuthUser | null;
6
+ session: import("../../types.js").ClientAuthSession | null;
7
+ signOut: (options?: import("../composables/useUserSession.js").SignOutOptions) => Promise<void>;
8
+ }) => any;
9
+ } & {
10
+ placeholder?: (props: {}) => any;
11
+ };
11
12
  };
13
+ type __VLS_Slots = ReturnType<typeof __VLS_template>['__VLS_Slots'];
12
14
  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
15
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
14
16
  declare const _default: typeof __VLS_export;
@@ -97,7 +97,7 @@ function requestBody(req) {
97
97
  }
98
98
  const body = req.rawBody ?? req.body;
99
99
  if (body === void 0 || body === null)
100
- return "__unenv__" in req ? void 0 : req;
100
+ return req.readable ? req : void 0;
101
101
  if (body.constructor === Object)
102
102
  return JSON.stringify(body);
103
103
  return body;
@@ -10,9 +10,10 @@ const requestSchema = z.discriminatedUnion("action", [
10
10
  const ownedUsers = /* @__PURE__ */ new Set();
11
11
  export default defineEventHandler(async (event) => {
12
12
  const token = useRuntimeConfig().betterAuthTestToken;
13
- if (!token || toWebRequest(event).headers.get("x-nuxt-auth-test") !== token)
13
+ const request = toWebRequest(event);
14
+ if (!token || request.headers.get("x-nuxt-auth-test") !== token)
14
15
  throw createAuthError(404, "Not found");
15
- const body = requestSchema.parse(parseJSON(await toWebRequest(event).text()));
16
+ const body = requestSchema.parse(parseJSON(await request.text()));
16
17
  const context = await serverAuth(event).$context;
17
18
  const test = context.test;
18
19
  if (body.action === "createUser") {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nuxtjs/better-auth",
3
3
  "type": "module",
4
- "version": "0.3.14",
4
+ "version": "0.3.16",
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,7 +61,7 @@
61
61
  "peerDependencies": {
62
62
  "@nuxt/test-utils": "^4.1.0",
63
63
  "@nuxthub/core": ">=0.10.5",
64
- "auth": "1.7.13",
64
+ "auth": "1.7.18",
65
65
  "better-auth": ">=1.7.3 <2"
66
66
  },
67
67
  "peerDependenciesMeta": {
@@ -76,58 +76,58 @@
76
76
  }
77
77
  },
78
78
  "dependencies": {
79
- "@nuxt/devtools-kit": "^3.4.1",
80
- "@nuxt/kit": "^4.6.0",
81
- "@types/node": "^24.13.3",
79
+ "@nuxt/devtools-kit": "^4.0.0",
80
+ "@nuxt/kit": "^4.6.2",
81
+ "@types/node": "^26.0.0",
82
82
  "consola": "^3.4.2",
83
83
  "cookie-es": "^3.1.1",
84
84
  "defu": "^6.1.7",
85
85
  "get-port-please": "^3.2.0",
86
- "h3": "^2.0.0",
86
+ "h3": "^2.0.8",
87
87
  "jiti": "^2.7.0",
88
- "nostics": "^1.2.0",
88
+ "nostics": "^1.3.0",
89
89
  "pathe": "^2.0.3",
90
90
  "radix3": "^1.1.2",
91
- "std-env": "^4.2.0",
91
+ "std-env": "^4.3.0",
92
92
  "ufo": "^1.6.4",
93
- "zod": "^4.4.3"
93
+ "zod": "^4.6.7"
94
94
  },
95
95
  "devDependencies": {
96
96
  "@antfu/eslint-config": "^10.0.0",
97
97
  "@libsql/client": "^0.18.0",
98
98
  "@libsql/linux-x64-gnu": "0.5.29",
99
- "@nuxt/devtools": "^3.4.1",
99
+ "@nuxt/devtools": "^4.0.0",
100
100
  "@nuxt/fonts": "1.2.0",
101
101
  "@nuxt/module-builder": "^1.0.3",
102
- "@nuxt/schema": "^4.6.0",
103
- "@nuxt/test-utils": "^4.3.3",
104
- "@nuxthub/core": "^0.10.8",
105
- "@pinia/nuxt": "^1.0.2",
102
+ "@nuxt/schema": "^4.6.2",
103
+ "@nuxt/test-utils": "^4.3.4",
104
+ "@nuxthub/core": "^0.10.11",
105
+ "@pinia/nuxt": "^1.0.3",
106
106
  "@types/better-sqlite3": "^9.6.0",
107
107
  "@typescript/typescript6": "6.0.2",
108
- "@vue/test-utils": "^2.4.6",
109
- "auth": "1.7.13",
110
- "better-auth": "1.7.13",
111
- "better-call": "1.4.4",
112
- "better-sqlite3": "^13.0.0",
113
- "drizzle-kit": "^0.31.10",
114
- "drizzle-orm": "^0.45.2",
115
- "eslint": "^10.8.1",
116
- "happy-dom": "^21.0.0",
117
- "nitropack": "2.13.5",
118
- "nuxt": "^4.6.0",
119
- "pinia": "^4.0.3",
120
- "pkg-pr-new": "0.0.92",
121
- "playwright-core": "1.64.1",
122
- "postgres": "^3.4.9",
108
+ "@vue/test-utils": "^2.5.1",
109
+ "auth": "1.7.18",
110
+ "better-auth": "1.7.18",
111
+ "better-call": "1.4.5",
112
+ "better-sqlite3": "^13.0.3",
113
+ "drizzle-kit": "^0.31.11",
114
+ "drizzle-orm": "^0.45.4",
115
+ "eslint": "^10.13.0",
116
+ "happy-dom": "^21.0.4",
117
+ "nitropack": "2.13.6",
118
+ "nuxt": "^4.6.2",
119
+ "pinia": "^4.1.0",
120
+ "pkg-pr-new": "0.0.93",
121
+ "playwright-core": "1.65.0",
122
+ "postgres": "^4.0.0",
123
123
  "typescript": "~7.0.0",
124
124
  "typescript-next": "npm:typescript@~7.0.0",
125
125
  "unstorage": "^1.17.5",
126
- "vitest": "^5.0.0",
127
- "vue": "3.5.44",
128
- "vue-tsc": "^3.3.10",
129
- "wrangler": "4.152.0",
130
- "yaml": "^2.9.0"
126
+ "vitest": "^5.0.5",
127
+ "vue": "3.5.45",
128
+ "vue-tsc": "^3.3.13",
129
+ "wrangler": "4.158.0",
130
+ "yaml": "^2.9.1"
131
131
  },
132
132
  "scripts": {
133
133
  "build": "pnpm build:docs",