@onmax/nuxt-better-auth 0.0.1 → 0.0.2-alpha.2

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.
Files changed (50) hide show
  1. package/README.md +17 -170
  2. package/dist/module.d.mts +20 -2
  3. package/dist/module.json +1 -1
  4. package/dist/module.mjs +363 -14
  5. package/dist/runtime/app/components/BetterAuthState.d.vue.ts +20 -0
  6. package/dist/runtime/app/components/BetterAuthState.vue +8 -0
  7. package/dist/runtime/app/components/BetterAuthState.vue.d.ts +20 -0
  8. package/dist/runtime/app/composables/useUserSession.d.ts +20 -0
  9. package/dist/runtime/app/composables/useUserSession.js +158 -0
  10. package/dist/runtime/app/middleware/auth.global.d.ts +13 -0
  11. package/dist/runtime/app/middleware/auth.global.js +31 -0
  12. package/dist/runtime/app/pages/__better-auth-devtools.d.vue.ts +3 -0
  13. package/dist/runtime/app/pages/__better-auth-devtools.vue +426 -0
  14. package/dist/runtime/app/pages/__better-auth-devtools.vue.d.ts +3 -0
  15. package/dist/runtime/app/plugins/session.client.d.ts +2 -0
  16. package/dist/runtime/app/plugins/session.client.js +16 -0
  17. package/dist/runtime/app/plugins/session.server.d.ts +2 -0
  18. package/dist/runtime/app/plugins/session.server.js +23 -0
  19. package/dist/runtime/config.d.ts +36 -0
  20. package/dist/runtime/config.js +6 -0
  21. package/dist/runtime/server/api/_better-auth/_schema.d.ts +8 -0
  22. package/dist/runtime/server/api/_better-auth/_schema.js +11 -0
  23. package/dist/runtime/server/api/_better-auth/accounts.get.d.ts +14 -0
  24. package/dist/runtime/server/api/_better-auth/accounts.get.js +28 -0
  25. package/dist/runtime/server/api/_better-auth/config.get.d.ts +35 -0
  26. package/dist/runtime/server/api/_better-auth/config.get.js +46 -0
  27. package/dist/runtime/server/api/_better-auth/sessions.delete.d.ts +4 -0
  28. package/dist/runtime/server/api/_better-auth/sessions.delete.js +22 -0
  29. package/dist/runtime/server/api/_better-auth/sessions.get.d.ts +14 -0
  30. package/dist/runtime/server/api/_better-auth/sessions.get.js +34 -0
  31. package/dist/runtime/server/api/_better-auth/users.get.d.ts +14 -0
  32. package/dist/runtime/server/api/_better-auth/users.get.js +34 -0
  33. package/dist/runtime/server/api/auth/[...all].d.ts +2 -0
  34. package/dist/runtime/server/api/auth/[...all].js +6 -0
  35. package/dist/runtime/server/middleware/route-access.d.ts +2 -0
  36. package/dist/runtime/server/middleware/route-access.js +28 -0
  37. package/dist/runtime/server/tsconfig.json +3 -0
  38. package/dist/runtime/server/utils/auth.d.ts +10 -0
  39. package/dist/runtime/server/utils/auth.js +32 -0
  40. package/dist/runtime/server/utils/session.d.ts +9 -0
  41. package/dist/runtime/server/utils/session.js +22 -0
  42. package/dist/runtime/types/augment.d.ts +42 -0
  43. package/dist/runtime/types/augment.js +0 -0
  44. package/dist/runtime/types.d.ts +23 -0
  45. package/dist/runtime/types.js +0 -0
  46. package/dist/runtime/utils/match-user.d.ts +2 -0
  47. package/dist/runtime/utils/match-user.js +13 -0
  48. package/dist/types.d.mts +8 -10
  49. package/package.json +35 -10
  50. package/dist/module.d.cts +0 -2
package/README.md CHANGED
@@ -1,180 +1,27 @@
1
- # @onmax/nuxt-better-auth
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/onmax/nuxt-better-auth/main/.github/og.png" alt="Nuxt Better Auth" width="100%">
3
+ <br>
4
+ <sub>Designed by <a href="https://github.com/HugoRCD">HugoRCD</a></sub>
5
+ </p>
2
6
 
3
- [![npm version][npm-version-src]][npm-version-href]
4
- [![npm downloads][npm-downloads-src]][npm-downloads-href]
5
- [![License][license-src]][license-href]
6
- [![Nuxt][nuxt-src]][nuxt-href]
7
+ <h1 align="center">@onmax/nuxt-better-auth</h1>
7
8
 
8
- Nuxt module for [Better Auth](https://better-auth.com) with auto schema generation, route protection, and session management. Works with [NuxtHub](https://hub.nuxt.com) and future `@nuxt/db`.
9
+ <p align="center">Nuxt module for <a href="https://better-auth.com">Better Auth</a></p>
9
10
 
10
- ## Features
11
+ <p align="center">
12
+ <a href="https://npmjs.com/package/@onmax/nuxt-better-auth"><img src="https://img.shields.io/npm/v/@onmax/nuxt-better-auth/latest.svg?style=flat&colorA=020420&colorB=00DC82" alt="npm version"></a>
13
+ <a href="https://npm.chart.dev/@onmax/nuxt-better-auth"><img src="https://img.shields.io/npm/dm/@onmax/nuxt-better-auth.svg?style=flat&colorA=020420&colorB=00DC82" alt="npm downloads"></a>
14
+ <a href="https://npmjs.com/package/@onmax/nuxt-better-auth"><img src="https://img.shields.io/npm/l/@onmax/nuxt-better-auth.svg?style=flat&colorA=020420&colorB=00DC82" alt="License"></a>
15
+ <a href="https://nuxt.com"><img src="https://img.shields.io/badge/Nuxt-020420?logo=nuxt.js" alt="Nuxt"></a>
16
+ </p>
11
17
 
12
- - **Auto Schema Generation** - Generates Drizzle schema from your better-auth plugins
13
- - **Route Protection** - Declarative access rules via `routeRules`
14
- - **Session Management** - SSR-safe session handling with client hydration
15
- - **Role-Based Access** - Support for `admin`, `user`, and custom roles
16
- - **Auto-Imports** - `useUserSession`, `requireUserSession`, `getUserSession`
17
- - **BetterAuthState Component** - Ready-to-use Vue component with slots
18
+ > [!WARNING]
19
+ > This library is a work in progress and not ready for production use.
18
20
 
19
- ## Requirements
21
+ ## Documentation
20
22
 
21
- - NuxtHub with database enabled (`hub: { database: true }`) or future `@nuxt/db`
22
-
23
- ## Quick Start
24
-
25
- ### 1. Install
26
-
27
- ```bash
28
- pnpm add @onmax/nuxt-better-auth better-auth drizzle-orm @nuxthub/core
29
- ```
30
-
31
- ### 2. Configure Nuxt
32
-
33
- ```ts
34
- export default defineNuxtConfig({
35
- modules: ['@nuxthub/core', '@onmax/nuxt-better-auth'],
36
-
37
- hub: { database: true },
38
-
39
- runtimeConfig: {
40
- betterAuthSecret: '', // BETTER_AUTH_SECRET env var
41
- public: { siteUrl: 'http://localhost:3000' },
42
- },
43
-
44
- routeRules: {
45
- '/app/**': { auth: 'user' },
46
- '/admin/**': { auth: { role: 'admin' } },
47
- '/login': { auth: 'guest' },
48
- },
49
- })
50
- ```
51
-
52
- ### 3. Create Server Config
53
-
54
- Create `server/auth.config.ts`:
55
-
56
- ```ts
57
- import { admin } from 'better-auth/plugins'
58
- import { defineServerAuth } from '@onmax/nuxt-better-auth'
59
-
60
- export default defineServerAuth(({ db }) => ({
61
- appName: 'My App',
62
- plugins: [admin()],
63
- emailAndPassword: { enabled: true },
64
- }))
65
- ```
66
-
67
- > Schema is auto-generated from your plugins! No manual Drizzle schema needed.
68
-
69
- ### 4. Create Client Config
70
-
71
- Create `app/auth.client.ts`:
72
-
73
- ```ts
74
- import { adminClient } from 'better-auth/client/plugins'
75
- import { createAuthClient } from 'better-auth/vue'
76
-
77
- export function createAppAuthClient(baseURL: string) {
78
- return createAuthClient({
79
- baseURL,
80
- plugins: [adminClient()],
81
- })
82
- }
83
-
84
- export type AppAuthClient = ReturnType<typeof createAppAuthClient>
85
- ```
86
-
87
- ### 5. Add Type Extensions
88
-
89
- Create `shared/types/auth.d.ts`:
90
-
91
- ```ts
92
- import '#nuxt-better-auth'
93
-
94
- declare module '#nuxt-better-auth' {
95
- interface AuthUser {
96
- role?: string | null
97
- banned?: boolean | null
98
- }
99
- }
100
- ```
101
-
102
- ## Route Rules
103
-
104
- | Option | Type | Description |
105
- |--------|------|-------------|
106
- | `auth` | `false \| 'guest' \| 'user' \| { role: string }` | Auth requirement |
107
-
108
- Examples:
109
- - `auth: false` - Public (default)
110
- - `auth: 'guest'` - Only unauthenticated users
111
- - `auth: 'user'` - Any authenticated user
112
- - `auth: { role: 'admin' }` - Requires specific role
113
-
114
- ## Composables
115
-
116
- ### `useUserSession()`
117
-
118
- ```ts
119
- const { user, session, loggedIn, ready, client } = useUserSession()
120
- ```
121
-
122
- ### `<BetterAuthState>`
123
-
124
- ```vue
125
- <BetterAuthState>
126
- <template #default="{ loggedIn, user, signOut }">
127
- <p v-if="loggedIn">Welcome, {{ user?.name }}</p>
128
- <p v-else>Not logged in</p>
129
- </template>
130
- <template #placeholder>
131
- <p>Loading...</p>
132
- </template>
133
- </BetterAuthState>
134
- ```
135
-
136
- ## Server Utils
137
-
138
- ```ts
139
- // Require auth
140
- const { user, session } = await requireUserSession(event)
141
-
142
- // Require admin
143
- const { user } = await requireUserSession(event, { role: 'admin' })
144
-
145
- // Optional session
146
- const session = await getUserSession(event)
147
- ```
148
-
149
- ## Module Aliases
150
-
151
- | Alias | Points To |
152
- |-------|-----------|
153
- | `#auth/server` | `server/auth.config.ts` |
154
- | `#auth/client` | `app/auth.client.ts` |
155
- | `#nuxt-better-auth` | Module type augmentation |
156
-
157
- ## Development
158
-
159
- ```bash
160
- pnpm install
161
- pnpm dev:prepare
162
- pnpm dev
163
- ```
23
+ **[nuxt-better-auth.onmax.me](https://nuxt-better-auth.onmax.me/)**
164
24
 
165
25
  ## License
166
26
 
167
27
  MIT
168
-
169
- <!-- Badges -->
170
- [npm-version-src]: https://img.shields.io/npm/v/@onmax/nuxt-better-auth/latest.svg?style=flat&colorA=020420&colorB=00DC82
171
- [npm-version-href]: https://npmjs.com/package/@onmax/nuxt-better-auth
172
-
173
- [npm-downloads-src]: https://img.shields.io/npm/dm/@onmax/nuxt-better-auth.svg?style=flat&colorA=020420&colorB=00DC82
174
- [npm-downloads-href]: https://npm.chart.dev/@onmax/nuxt-better-auth
175
-
176
- [license-src]: https://img.shields.io/npm/l/@onmax/nuxt-better-auth.svg?style=flat&colorA=020420&colorB=00DC82
177
- [license-href]: https://npmjs.com/package/@onmax/nuxt-better-auth
178
-
179
- [nuxt-src]: https://img.shields.io/badge/Nuxt-020420?logo=nuxt.js
180
- [nuxt-href]: https://nuxt.com
package/dist/module.d.mts CHANGED
@@ -1,2 +1,20 @@
1
- export * from "/home/maxi/nuxt/better-auth/src/module.js";
2
- export { default } from "/home/maxi/nuxt/better-auth/src/module.js";
1
+ import * as _nuxt_schema from '@nuxt/schema';
2
+ import { BetterAuthModuleOptions } from '../dist/runtime/config.js';
3
+ export { BetterAuthModuleOptions, defineClientAuth, defineServerAuth } from '../dist/runtime/config.js';
4
+ import { BetterAuthOptions } from 'better-auth';
5
+ export { Auth, AuthMeta, AuthMode, AuthRouteRules, AuthSession, AuthUser, InferSession, InferUser, RequireSessionOptions, ServerAuthContext, UserMatch } from '../dist/runtime/types.js';
6
+
7
+ declare module '@nuxt/schema' {
8
+ interface NuxtHooks {
9
+ /**
10
+ * Extend better-auth config with additional plugins or options.
11
+ * Called after user's auth.config.ts is loaded.
12
+ * @param config - Partial config to merge into the auth options
13
+ */
14
+ 'better-auth:config:extend': (config: Partial<BetterAuthOptions>) => void | Promise<void>;
15
+ }
16
+ }
17
+
18
+ declare const _default: _nuxt_schema.NuxtModule<BetterAuthModuleOptions, BetterAuthModuleOptions, false>;
19
+
20
+ export { _default as default };
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">=3.0.0"
6
6
  },
7
- "version": "0.0.1",
7
+ "version": "0.0.2-alpha.2",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -1,20 +1,369 @@
1
- import { createJiti } from "file:///home/maxi/nuxt/better-auth/node_modules/.pnpm/jiti@2.6.1/node_modules/jiti/lib/jiti.mjs";
1
+ import { existsSync } from 'node:fs';
2
+ import { mkdir, writeFile } from 'node:fs/promises';
3
+ import { defineNuxtModule, createResolver, hasNuxtModule, addTemplate, addTypeTemplate, updateTemplates, addServerImportsDir, addServerScanDir, addServerHandler, addImportsDir, addPlugin, addComponentsDir, extendPages } from '@nuxt/kit';
4
+ import { consola as consola$1 } from 'consola';
5
+ import { defu } from 'defu';
6
+ import { join } from 'pathe';
7
+ import { toRouteMatcher, createRouter } from 'radix3';
8
+ export { defineClientAuth, defineServerAuth } from '../dist/runtime/config.js';
2
9
 
3
- const jiti = createJiti(import.meta.url, {
4
- "interopDefault": true,
5
- "alias": {
6
- "@onmax/nuxt-better-auth": "/home/maxi/nuxt/better-auth"
10
+ function setupDevTools(nuxt) {
11
+ nuxt.hook("devtools:customTabs", (tabs) => {
12
+ tabs.push({
13
+ category: "server",
14
+ name: "better-auth",
15
+ title: "Auth",
16
+ icon: "simple-icons:betterauth",
17
+ view: {
18
+ type: "iframe",
19
+ src: "/__better-auth-devtools"
20
+ }
21
+ });
22
+ });
23
+ }
24
+
25
+ function generateDrizzleSchema(tables, dialect) {
26
+ const imports = getImports(dialect);
27
+ const tableDefinitions = Object.entries(tables).map(([tableName, table]) => generateTable(tableName, table, dialect, tables)).join("\n\n");
28
+ return `${imports}
29
+
30
+ ${tableDefinitions}
31
+ `;
32
+ }
33
+ function getImports(dialect) {
34
+ switch (dialect) {
35
+ case "sqlite":
36
+ return `import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'`;
37
+ case "postgresql":
38
+ return `import { boolean, pgTable, text, timestamp, integer } from 'drizzle-orm/pg-core'`;
39
+ case "mysql":
40
+ return `import { boolean, int, mysqlTable, text, timestamp, varchar } from 'drizzle-orm/mysql-core'`;
41
+ }
42
+ }
43
+ function generateTable(tableName, table, dialect, allTables) {
44
+ const tableFunc = dialect === "sqlite" ? "sqliteTable" : dialect === "postgresql" ? "pgTable" : "mysqlTable";
45
+ const dbTableName = table.modelName || tableName;
46
+ const fields = Object.entries(table.fields).map(([fieldName, field]) => generateField(fieldName, field, dialect, allTables)).join(",\n ");
47
+ const idField = generateIdField(dialect);
48
+ return `export const ${tableName} = ${tableFunc}('${dbTableName}', {
49
+ ${idField},
50
+ ${fields}
51
+ })`;
52
+ }
53
+ function generateIdField(dialect) {
54
+ switch (dialect) {
55
+ case "sqlite":
56
+ case "postgresql":
57
+ return `id: text('id').primaryKey()`;
58
+ case "mysql":
59
+ return `id: varchar('id', { length: 36 }).primaryKey()`;
60
+ }
61
+ }
62
+ function generateField(fieldName, field, dialect, allTables) {
63
+ const dbFieldName = fieldName;
64
+ let fieldDef = getFieldType(field.type, dialect, dbFieldName);
65
+ if (field.required && field.defaultValue === void 0)
66
+ fieldDef += ".notNull()";
67
+ if (field.unique)
68
+ fieldDef += ".unique()";
69
+ if (field.defaultValue !== void 0) {
70
+ if (typeof field.defaultValue === "boolean")
71
+ fieldDef += `.default(${field.defaultValue})`;
72
+ else if (typeof field.defaultValue === "string")
73
+ fieldDef += `.default('${field.defaultValue}')`;
74
+ else
75
+ fieldDef += `.default(${field.defaultValue})`;
76
+ if (field.required)
77
+ fieldDef += ".notNull()";
78
+ }
79
+ if (field.references) {
80
+ const refTable = field.references.model;
81
+ if (allTables[refTable])
82
+ fieldDef += `.references(() => ${refTable}.${field.references.field})`;
83
+ }
84
+ return `${fieldName}: ${fieldDef}`;
85
+ }
86
+ function getFieldType(type, dialect, fieldName) {
87
+ const normalizedType = Array.isArray(type) ? "string" : type;
88
+ switch (dialect) {
89
+ case "sqlite":
90
+ return getSqliteType(normalizedType, fieldName);
91
+ case "postgresql":
92
+ return getPostgresType(normalizedType, fieldName);
93
+ case "mysql":
94
+ return getMysqlType(normalizedType, fieldName);
95
+ }
96
+ }
97
+ function getSqliteType(type, fieldName) {
98
+ switch (type) {
99
+ case "string":
100
+ return `text('${fieldName}')`;
101
+ case "boolean":
102
+ return `integer('${fieldName}', { mode: 'boolean' })`;
103
+ case "date":
104
+ return `integer('${fieldName}', { mode: 'timestamp' })`;
105
+ case "number":
106
+ return `integer('${fieldName}')`;
107
+ default:
108
+ return `text('${fieldName}')`;
109
+ }
110
+ }
111
+ function getPostgresType(type, fieldName) {
112
+ switch (type) {
113
+ case "string":
114
+ return `text('${fieldName}')`;
115
+ case "boolean":
116
+ return `boolean('${fieldName}')`;
117
+ case "date":
118
+ return `timestamp('${fieldName}')`;
119
+ case "number":
120
+ return `integer('${fieldName}')`;
121
+ default:
122
+ return `text('${fieldName}')`;
123
+ }
124
+ }
125
+ function getMysqlType(type, fieldName) {
126
+ switch (type) {
127
+ case "string":
128
+ return `text('${fieldName}')`;
129
+ case "boolean":
130
+ return `boolean('${fieldName}')`;
131
+ case "date":
132
+ return `timestamp('${fieldName}')`;
133
+ case "number":
134
+ return `int('${fieldName}')`;
135
+ default:
136
+ return `text('${fieldName}')`;
137
+ }
138
+ }
139
+ async function loadUserAuthConfig(configPath) {
140
+ const { createJiti } = await import('jiti');
141
+ const jiti = createJiti(import.meta.url, { interopDefault: true });
142
+ try {
143
+ const mod = await jiti.import(configPath);
144
+ const configFn = mod.default || mod;
145
+ if (typeof configFn === "function") {
146
+ return configFn({ runtimeConfig: {}, db: null });
147
+ }
148
+ return {};
149
+ } catch (error) {
150
+ consola$1.error("[@onmax/nuxt-better-auth] Failed to load auth config for schema generation. Schema may be incomplete:", error);
151
+ return {};
152
+ }
153
+ }
154
+
155
+ const consola = consola$1.withTag("nuxt-better-auth");
156
+ const module$1 = defineNuxtModule({
157
+ meta: { name: "@onmax/nuxt-better-auth", configKey: "auth", compatibility: { nuxt: ">=3.0.0" } },
158
+ defaults: {
159
+ serverConfig: "server/auth.config",
160
+ clientConfig: "app/auth.config",
161
+ redirects: { login: "/login", guest: "/" },
162
+ secondaryStorage: false
7
163
  },
8
- "transformOptions": {
9
- "babel": {
10
- "plugins": []
164
+ async setup(options, nuxt) {
165
+ const resolver = createResolver(import.meta.url);
166
+ const serverConfigFile = options.serverConfig;
167
+ const clientConfigFile = options.clientConfig;
168
+ const serverConfigPath = resolver.resolve(nuxt.options.rootDir, serverConfigFile);
169
+ const clientConfigPath = resolver.resolve(nuxt.options.rootDir, clientConfigFile);
170
+ const serverConfigExists = existsSync(`${serverConfigPath}.ts`) || existsSync(`${serverConfigPath}.js`);
171
+ const clientConfigExists = existsSync(`${clientConfigPath}.ts`) || existsSync(`${clientConfigPath}.js`);
172
+ if (!serverConfigExists)
173
+ throw new Error(`[nuxt-better-auth] Missing ${serverConfigFile}.ts - create with defineServerAuth()`);
174
+ if (!clientConfigExists)
175
+ throw new Error(`[nuxt-better-auth] Missing ${clientConfigFile}.ts - export createAppAuthClient()`);
176
+ const hasNuxtHub = hasNuxtModule("@nuxthub/core", nuxt);
177
+ const hub = hasNuxtHub ? nuxt.options.hub : void 0;
178
+ const hasHubDb = hasNuxtHub && !!hub?.db;
179
+ let secondaryStorageEnabled = options.secondaryStorage ?? false;
180
+ if (secondaryStorageEnabled && (!hasNuxtHub || !hub?.kv)) {
181
+ consola.warn("secondaryStorage requires @nuxthub/core with hub.kv: true. Disabling.");
182
+ secondaryStorageEnabled = false;
11
183
  }
184
+ nuxt.options.runtimeConfig.public = nuxt.options.runtimeConfig.public || {};
185
+ nuxt.options.runtimeConfig.public.auth = defu(nuxt.options.runtimeConfig.public.auth, {
186
+ redirects: { login: options.redirects?.login ?? "/login", guest: options.redirects?.guest ?? "/" },
187
+ useDatabase: hasHubDb
188
+ });
189
+ nuxt.options.runtimeConfig.betterAuthSecret ||= process.env.BETTER_AUTH_SECRET || process.env.NUXT_BETTER_AUTH_SECRET || "";
190
+ nuxt.options.runtimeConfig.auth = defu(nuxt.options.runtimeConfig.auth, {
191
+ secondaryStorage: secondaryStorageEnabled
192
+ });
193
+ nuxt.options.alias["#nuxt-better-auth"] = resolver.resolve("./runtime/types/augment");
194
+ nuxt.options.alias["#auth/server"] = serverConfigPath;
195
+ nuxt.options.alias["#auth/client"] = clientConfigPath;
196
+ const secondaryStorageCode = secondaryStorageEnabled ? `import { kv } from 'hub:kv'
197
+ export function createSecondaryStorage() {
198
+ return {
199
+ get: async (key) => kv.get(\`_auth:\${key}\`),
200
+ set: async (key, value, ttl) => kv.set(\`_auth:\${key}\`, value, { ttl }),
201
+ delete: async (key) => kv.del(\`_auth:\${key}\`),
202
+ }
203
+ }` : `export function createSecondaryStorage() { return undefined }`;
204
+ const secondaryStorageTemplate = addTemplate({ filename: "better-auth/secondary-storage.mjs", getContents: () => secondaryStorageCode, write: true });
205
+ nuxt.options.alias["#auth/secondary-storage"] = secondaryStorageTemplate.dst;
206
+ const hubDbPath = nuxt.options.alias["hub:db"];
207
+ const databaseCode = hasHubDb && hubDbPath ? `import { db, schema } from '${hubDbPath}'
208
+ import { drizzleAdapter } from 'better-auth/adapters/drizzle'
209
+ const rawDialect = '${hub?.db?.dialect ?? "sqlite"}'
210
+ const dialect = rawDialect === 'postgresql' ? 'pg' : rawDialect
211
+ export function createDatabase() { return drizzleAdapter(db, { provider: dialect, schema }) }
212
+ export { db }` : `export function createDatabase() { return undefined }
213
+ export const db = undefined`;
214
+ const databaseTemplate = addTemplate({ filename: "better-auth/database.mjs", getContents: () => databaseCode, write: true });
215
+ nuxt.options.alias["#auth/database"] = databaseTemplate.dst;
216
+ addTypeTemplate({
217
+ filename: "types/auth-secondary-storage.d.ts",
218
+ getContents: () => `
219
+ declare module '#auth/secondary-storage' {
220
+ interface SecondaryStorage {
221
+ get: (key: string) => Promise<string | null>
222
+ set: (key: string, value: unknown, ttl?: number) => Promise<void>
223
+ delete: (key: string) => Promise<void>
12
224
  }
13
- })
225
+ export function createSecondaryStorage(): SecondaryStorage | undefined
226
+ }
227
+ `
228
+ });
229
+ addTypeTemplate({
230
+ filename: "types/auth-database.d.ts",
231
+ getContents: () => `
232
+ declare module '#auth/database' {
233
+ import type { drizzleAdapter } from 'better-auth/adapters/drizzle'
234
+ export function createDatabase(): ReturnType<typeof drizzleAdapter> | undefined
235
+ export const db: unknown
236
+ }
237
+ `
238
+ });
239
+ addTypeTemplate({
240
+ filename: "types/nuxt-better-auth.d.ts",
241
+ getContents: () => `
242
+ export * from '${resolver.resolve("./runtime/types/augment")}'
243
+ export type { AuthMeta, AuthMode, AuthRouteRules, UserMatch, RequireSessionOptions, Auth, InferUser, InferSession } from '${resolver.resolve("./runtime/types")}'
244
+ `
245
+ });
246
+ addTypeTemplate({
247
+ filename: "types/nuxt-better-auth-infer.d.ts",
248
+ getContents: () => `
249
+ import type { InferUser, InferSession } from 'better-auth'
250
+ import type { RuntimeConfig } from 'nuxt/schema'
251
+ import type configFn from '${serverConfigPath}'
252
+
253
+ type _Config = ReturnType<typeof configFn>
14
254
 
15
- /** @type {import("/home/maxi/nuxt/better-auth/src/module.js")} */
16
- const _module = await jiti.import("/home/maxi/nuxt/better-auth/src/module.ts");
255
+ declare module '#nuxt-better-auth' {
256
+ interface AuthUser extends InferUser<_Config> {}
257
+ interface AuthSession { session: InferSession<_Config>['session'], user: InferUser<_Config> }
258
+ interface ServerAuthContext {
259
+ runtimeConfig: RuntimeConfig
260
+ ${hasHubDb ? `db: typeof import('hub:db')['db']` : ""}
261
+ }
262
+ }
263
+ `
264
+ });
265
+ addTypeTemplate({
266
+ filename: "types/nuxt-better-auth-client.d.ts",
267
+ getContents: () => `
268
+ import type { createAppAuthClient } from '${clientConfigPath}'
269
+ declare module '#nuxt-better-auth' {
270
+ export type AppAuthClient = ReturnType<typeof createAppAuthClient>
271
+ }
272
+ `
273
+ });
274
+ addTypeTemplate({
275
+ filename: "types/nuxt-better-auth-nitro.d.ts",
276
+ getContents: () => `
277
+ declare module 'nitropack/types' {
278
+ interface NitroRouteRules {
279
+ auth?: import('${resolver.resolve("./runtime/types")}').AuthMeta
280
+ }
281
+ }
282
+ `
283
+ });
284
+ nuxt.hook("builder:watch", async (_event, relativePath) => {
285
+ if (relativePath.includes("auth.config")) {
286
+ await updateTemplates({ filter: (t) => t.filename.includes("nuxt-better-auth") });
287
+ }
288
+ });
289
+ addServerImportsDir(resolver.resolve("./runtime/server/utils"));
290
+ addServerScanDir(resolver.resolve("./runtime/server/middleware"));
291
+ addServerHandler({ route: "/api/auth/**", handler: resolver.resolve("./runtime/server/api/auth/[...all]") });
292
+ addImportsDir(resolver.resolve("./runtime/app/composables"));
293
+ addImportsDir(resolver.resolve("./runtime/utils"));
294
+ addPlugin({ src: resolver.resolve("./runtime/app/plugins/session.server"), mode: "server" });
295
+ addPlugin({ src: resolver.resolve("./runtime/app/plugins/session.client"), mode: "client" });
296
+ addComponentsDir({ path: resolver.resolve("./runtime/app/components") });
297
+ nuxt.hook("app:resolve", (app) => {
298
+ app.middleware.push({ name: "auth", path: resolver.resolve("./runtime/app/middleware/auth.global"), global: true });
299
+ });
300
+ if (hasHubDb) {
301
+ await setupBetterAuthSchema(nuxt, serverConfigPath);
302
+ }
303
+ if (nuxt.options.dev && process.env.NODE_ENV !== "production") {
304
+ setupDevTools(nuxt);
305
+ addServerHandler({ route: "/api/_better-auth/config", method: "get", handler: resolver.resolve("./runtime/server/api/_better-auth/config.get") });
306
+ if (hasHubDb) {
307
+ addServerHandler({ route: "/api/_better-auth/sessions", method: "get", handler: resolver.resolve("./runtime/server/api/_better-auth/sessions.get") });
308
+ addServerHandler({ route: "/api/_better-auth/sessions", method: "delete", handler: resolver.resolve("./runtime/server/api/_better-auth/sessions.delete") });
309
+ addServerHandler({ route: "/api/_better-auth/users", method: "get", handler: resolver.resolve("./runtime/server/api/_better-auth/users.get") });
310
+ addServerHandler({ route: "/api/_better-auth/accounts", method: "get", handler: resolver.resolve("./runtime/server/api/_better-auth/accounts.get") });
311
+ }
312
+ extendPages((pages) => {
313
+ pages.push({ name: "better-auth-devtools", path: "/__better-auth-devtools", file: resolver.resolve("./runtime/app/pages/__better-auth-devtools.vue") });
314
+ });
315
+ }
316
+ nuxt.hook("pages:extend", (pages) => {
317
+ const routeRules = nuxt.options.routeRules || {};
318
+ if (!Object.keys(routeRules).length)
319
+ return;
320
+ const matcher = toRouteMatcher(createRouter({ routes: routeRules }));
321
+ const applyMetaFromRules = (page) => {
322
+ const matches = matcher.matchAll(page.path);
323
+ if (!matches.length)
324
+ return;
325
+ const matchedRules = defu({}, ...matches.reverse());
326
+ if (matchedRules.auth !== void 0) {
327
+ page.meta = page.meta || {};
328
+ page.meta.auth = matchedRules.auth;
329
+ }
330
+ page.children?.forEach((child) => applyMetaFromRules(child));
331
+ };
332
+ pages.forEach((page) => applyMetaFromRules(page));
333
+ });
334
+ }
335
+ });
336
+ async function setupBetterAuthSchema(nuxt, serverConfigPath) {
337
+ const hub = nuxt.options.hub;
338
+ const dialect = typeof hub.db === "string" ? hub.db : hub.db?.dialect;
339
+ if (!dialect || !["sqlite", "postgresql", "mysql"].includes(dialect)) {
340
+ consola.warn(`Unsupported database dialect: ${dialect}`);
341
+ return;
342
+ }
343
+ try {
344
+ const configFile = `${serverConfigPath}.ts`;
345
+ const userConfig = await loadUserAuthConfig(configFile);
346
+ const extendedConfig = {};
347
+ await nuxt.callHook("better-auth:config:extend", extendedConfig);
348
+ const plugins = [...userConfig.plugins || [], ...extendedConfig.plugins || []];
349
+ const { getAuthTables } = await import('better-auth/db');
350
+ const tables = getAuthTables({ plugins });
351
+ const schemaCode = generateDrizzleSchema(tables, dialect);
352
+ const schemaDir = join(nuxt.options.buildDir, "better-auth");
353
+ const schemaPath = join(schemaDir, `schema.${dialect}.ts`);
354
+ await mkdir(schemaDir, { recursive: true });
355
+ await writeFile(schemaPath, schemaCode);
356
+ addTemplate({ filename: `better-auth/schema.${dialect}.ts`, getContents: () => schemaCode, write: true });
357
+ consola.info(`Generated ${dialect} schema with ${Object.keys(tables).length} tables`);
358
+ } catch (error) {
359
+ consola.error("Failed to generate schema:", error);
360
+ }
361
+ nuxt.hook("hub:db:schema:extend", ({ paths, dialect: hookDialect }) => {
362
+ const schemaPath = join(nuxt.options.buildDir, "better-auth", `schema.${hookDialect}.ts`);
363
+ if (existsSync(schemaPath)) {
364
+ paths.push(schemaPath);
365
+ }
366
+ });
367
+ }
17
368
 
18
- export default _module?.default ?? _module;
19
- export const defineClientAuth = _module.defineClientAuth;
20
- export const defineServerAuth = _module.defineServerAuth;
369
+ export { module$1 as default };
@@ -0,0 +1,20 @@
1
+ declare var __VLS_1: {
2
+ loggedIn: any;
3
+ user: any;
4
+ session: any;
5
+ signOut: any;
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,8 @@
1
+ <script setup>
2
+ const { loggedIn, user, session, signOut, ready } = useUserSession();
3
+ </script>
4
+
5
+ <template>
6
+ <slot v-if="ready" v-bind="{ loggedIn, user, session, signOut }" />
7
+ <slot v-else name="placeholder" />
8
+ </template>
@@ -0,0 +1,20 @@
1
+ declare var __VLS_1: {
2
+ loggedIn: any;
3
+ user: any;
4
+ session: any;
5
+ signOut: any;
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
+ };