better-auth-nuxt 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/module.d.mts CHANGED
@@ -16,6 +16,10 @@ interface ModuleOptions {
16
16
  * @default ['*.better-auth']
17
17
  */
18
18
  serverConfigs?: string[];
19
+ /**
20
+ * @default ['*.better-auth-client']
21
+ */
22
+ clientConfigs?: string[];
19
23
  options: {
20
24
  /**
21
25
  * client options object or path to client setup script
@@ -30,9 +34,9 @@ interface ModuleOptions {
30
34
  * redirect options
31
35
  */
32
36
  redirectOptions: {
33
- redirectUserTo: string;
34
- redirectGuestTo: string;
35
- redirectUnauthorizedTo: string;
37
+ redirectUserTo?: string;
38
+ redirectGuestTo?: string;
39
+ redirectUnauthorizedTo?: string;
36
40
  };
37
41
  }
38
42
  interface ModulePublicRuntimeConfig {
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "better-auth",
3
3
  "configKey": "betterAuth",
4
- "version": "0.0.2",
4
+ "version": "0.0.4",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.1",
7
7
  "unbuild": "3.5.0"
package/dist/module.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import fs from 'node:fs';
2
- import { defineNuxtModule, createResolver, logger, addImportsDir, addServerHandler, addTypeTemplate, addServerImports, addPlugin, addTemplate } from '@nuxt/kit';
2
+ import { defineNuxtModule, createResolver, logger, addServerHandler, addTypeTemplate, addServerImports, addImports, addRouteMiddleware, addPlugin, addTemplate } from '@nuxt/kit';
3
3
  import { defu } from 'defu';
4
4
  import { resolve } from 'pathe';
5
5
  import { hash } from 'ohash';
@@ -33,6 +33,119 @@ async function serverAuth({ options }) {
33
33
  ].join("\n");
34
34
  }
35
35
 
36
+ async function useUserSession({ options }) {
37
+ return [
38
+ "import { createAuthClient } from 'better-auth/vue'",
39
+ ...options.configs.map((config) => {
40
+ return `import ${config.key} from "${config.path}"`;
41
+ }),
42
+ "import { defu } from 'defu'",
43
+ "import { computed, ref } from 'vue'",
44
+ "import { navigateTo, useRequestHeaders, useRequestURL, useRuntimeConfig, useState } from '#app'",
45
+ "",
46
+ "let _authInstance",
47
+ "",
48
+ "export function createAuthInstance() {",
49
+ " const url = useRequestURL()",
50
+ " const headers = import.meta.server ? useRequestHeaders() : undefined",
51
+ " const config = useRuntimeConfig()",
52
+ "",
53
+ " const authClient = createAuthClient({",
54
+ " baseURL: url.origin,",
55
+ " fetchOptions: {",
56
+ ...options.configs.map((config) => {
57
+ return ` ...${config.key}?.fetchOptions || {},`;
58
+ }),
59
+ " headers,",
60
+ " },",
61
+ ...options.configs.map((config) => {
62
+ return ` ${config.key},`;
63
+ }),
64
+ " plugins: [",
65
+ ...options.configs.map((config) => {
66
+ return ` ...${config.key}?.plugins || [],`;
67
+ }),
68
+ " ],",
69
+ " })",
70
+ "",
71
+ " const options = defu(config.public.betterAuth.redirectOptions || {}, {",
72
+ " redirectUserTo: '/profile',",
73
+ " redirectGuestTo: '/signin',",
74
+ " redirectUnauthorizedTo: '/401',",
75
+ " })",
76
+ "",
77
+ " const session = useState('auth:session', () => null)",
78
+ " const user = useState('auth:user', () => null)",
79
+ " const sessionFetching = import.meta.server ? ref(false) : useState('auth:sessionFetching', () => false)",
80
+ "",
81
+ " const fetchSession = async () => {",
82
+ " if (sessionFetching.value) {",
83
+ " return",
84
+ " }",
85
+ " sessionFetching.value = true",
86
+ " const { data } = await authClient.getSession({",
87
+ " fetchOptions: {",
88
+ " headers,",
89
+ " },",
90
+ " })",
91
+ " session.value = data?.session || null",
92
+ " user.value = data?.user || null",
93
+ " sessionFetching.value = false",
94
+ " return data",
95
+ " }",
96
+ "",
97
+ " return {",
98
+ " session,",
99
+ " user,",
100
+ " loggedIn: computed(() => !!session.value),",
101
+ " signIn: authClient.signIn,",
102
+ " signUp: authClient.signUp,",
103
+ " options,",
104
+ " fetchSession,",
105
+ " client: authClient,",
106
+ " signOut: async (options = {}) => {",
107
+ " try {",
108
+ " await authClient.signOut()",
109
+ " if (options.redirectTo)",
110
+ " await navigateTo(options.redirectTo)",
111
+ " }",
112
+ " catch (error) {",
113
+ " console.error('Sign out failed:', error)",
114
+ " throw error",
115
+ " }",
116
+ " },",
117
+ " }",
118
+ "}",
119
+ "",
120
+ "// Setup session listener for client-side updates",
121
+ "function setupSessionListener(client) {",
122
+ " if (!import.meta.client)",
123
+ " return",
124
+ "",
125
+ " client.$store.listen('$sessionSignal', async (signal) => {",
126
+ " if (!signal)",
127
+ " return",
128
+ " await client.useSession($fetch)",
129
+ " })",
130
+ "}",
131
+ "",
132
+ "export function useUserSession() {",
133
+ " if (_authInstance && import.meta.client)",
134
+ " return _authInstance",
135
+ "",
136
+ " const auth = createAuthInstance()",
137
+ "",
138
+ " if (import.meta.client) {",
139
+ " setupSessionListener(auth.client)",
140
+ " _authInstance = auth",
141
+ " }",
142
+ "",
143
+ " return auth",
144
+ "}",
145
+ ""
146
+ ].join("\n");
147
+ }
148
+
36
149
  const module = defineNuxtModule({
37
150
  meta: {
38
151
  name: "better-auth",
@@ -43,13 +156,19 @@ const module = defineNuxtModule({
43
156
  endpoint: "/api/auth/**",
44
157
  serverConfigs: [],
45
158
  redirectOptions: {
46
- redirectUserTo: "/profile",
47
- redirectGuestTo: "/signin",
159
+ redirectUserTo: "/auth/login",
160
+ redirectGuestTo: "/",
48
161
  redirectUnauthorizedTo: "/401"
49
162
  }
50
163
  },
51
164
  async setup(options, nuxt) {
52
165
  const resolver = createResolver(import.meta.url);
166
+ nuxt.options.vite.optimizeDeps ??= {};
167
+ nuxt.options.vite.optimizeDeps.include ??= [];
168
+ nuxt.options.vite.optimizeDeps.include.push(...[
169
+ "better-auth/client",
170
+ "better-auth/vue"
171
+ ]);
53
172
  if (!options.endpoint) {
54
173
  logger.withTag("better-auth").error("Missing endpoint option");
55
174
  }
@@ -59,7 +178,6 @@ const module = defineNuxtModule({
59
178
  redirectOptions: options.redirectOptions
60
179
  });
61
180
  nuxt.options.alias["#better-auth"] = resolve("./runtime");
62
- addImportsDir(resolve("./runtime/composables"));
63
181
  addServerHandler({
64
182
  route: options.endpoint,
65
183
  handler: resolver.resolve("./runtime/server/handler")
@@ -104,7 +222,6 @@ const module = defineNuxtModule({
104
222
  continue;
105
223
  }
106
224
  for (const path of [...paths, ...pathsJS]) {
107
- console.log("path", path);
108
225
  if (fs.existsSync(path)) {
109
226
  serverConfigs.push({
110
227
  key: pascalCase(hash(path)),
@@ -113,13 +230,13 @@ const module = defineNuxtModule({
113
230
  }
114
231
  }
115
232
  }
116
- registerTemplate({
117
- filename: "better-auth-configs.mjs",
233
+ const server = registerTemplate({
234
+ filename: "better-auth/server.mjs",
118
235
  getContents: serverAuth,
119
236
  options: { configs: serverConfigs }
120
237
  });
121
238
  addTypeTemplate({
122
- filename: "better-auth-configs.d.ts",
239
+ filename: "better-auth/server.d.ts",
123
240
  getContents: () => {
124
241
  return [
125
242
  'import { betterAuth } from "better-auth"',
@@ -138,16 +255,124 @@ const module = defineNuxtModule({
138
255
  ].join("\n");
139
256
  }
140
257
  });
258
+ const clientConfigs = [];
259
+ for (const layer of nuxt.options._layers) {
260
+ const paths = await glob([
261
+ "**/*.better-auth-client.ts",
262
+ ...options.clientConfigs?.map((pattern) => {
263
+ return `**/${pattern}.ts`;
264
+ }) || []
265
+ ], { onlyFiles: true, ignore: nuxt.options.ignore, dot: true, cwd: layer.config.rootDir, absolute: true });
266
+ const pathsJS = await glob([
267
+ "**/*.better-auth.js",
268
+ ...options.serverConfigs?.map((pattern) => {
269
+ return `**/${pattern}.js`;
270
+ }) || []
271
+ ], { cwd: layer.config.serverDir });
272
+ if (paths.length === 0 && pathsJS.length === 0) {
273
+ continue;
274
+ }
275
+ for (const path of [...paths, ...pathsJS]) {
276
+ if (fs.existsSync(path)) {
277
+ clientConfigs.push({
278
+ key: pascalCase(hash(path)),
279
+ path
280
+ });
281
+ }
282
+ }
283
+ }
284
+ const client = registerTemplate({
285
+ filename: "better-auth/client.mjs",
286
+ getContents: useUserSession,
287
+ options: { configs: clientConfigs }
288
+ });
289
+ addTypeTemplate({
290
+ filename: "better-auth/client.d.ts",
291
+ getContents: () => {
292
+ return [
293
+ 'import { createAuthInstance } from "./client.mjs"',
294
+ 'import type { ClientOptions, InferSessionFromClient, InferUserFromClient } from "better-auth"',
295
+ 'import type { RouteLocationRaw } from "vue-router"',
296
+ 'import { Ref, ComputedRef } from "vue"',
297
+ ...clientConfigs.map((config) => {
298
+ return `import ${config.key} from "${config.path}"`;
299
+ }),
300
+ "export interface RuntimeAuthConfig {",
301
+ " redirectUserTo: RouteLocationRaw | string",
302
+ " redirectGuestTo: RouteLocationRaw | string",
303
+ " redirectUnauthorizedTo: RouteLocationRaw | string",
304
+ "}",
305
+ "export interface AuthSignOutOptions {",
306
+ " redirectTo?: RouteLocationRaw",
307
+ "}",
308
+ "export type AuthClient = ReturnType<typeof createAuthInstance>",
309
+ "export declare const useUserSession: () => AuthClient"
310
+ ].join("\n");
311
+ }
312
+ });
141
313
  addServerImports([
142
314
  {
143
- from: "#better-auth-configs",
315
+ from: server.dst,
144
316
  name: "useAuth"
145
317
  },
146
318
  {
147
- from: "#better-auth-configs",
319
+ from: server.dst,
148
320
  name: "auth"
149
321
  }
150
322
  ]);
323
+ addImports([
324
+ {
325
+ from: client.dst,
326
+ name: "useUserSession"
327
+ },
328
+ {
329
+ from: client.dst,
330
+ name: "createAuthInstance"
331
+ }
332
+ ]);
333
+ addRouteMiddleware({
334
+ name: "auth",
335
+ path: resolver.resolve("./runtime/middleware/auth.ts"),
336
+ global: true
337
+ });
338
+ addTypeTemplate({
339
+ filename: "types/better-auth-middleware.d.ts",
340
+ getContents: () => {
341
+ return [
342
+ " type MiddlewareOptions = false | {",
343
+ " /**",
344
+ " * Only apply auth middleware to guest or user",
345
+ " */",
346
+ " only?:",
347
+ ' | "guest"',
348
+ ' | "user"',
349
+ ' | "member"',
350
+ ' | "admin"',
351
+ " /**",
352
+ " * Redirect authenticated user to this route",
353
+ " */",
354
+ " redirectUserTo?: string",
355
+ " /**",
356
+ " * Redirect guest to this route",
357
+ " */",
358
+ " redirectGuestTo?: string",
359
+ " redirectUnauthorizedTo?: string",
360
+ " }",
361
+ ' declare module "#app" {',
362
+ " interface PageMeta {",
363
+ " auth?: MiddlewareOptions",
364
+ " }",
365
+ " }",
366
+ ' declare module "vue-router" {',
367
+ " interface RouteMeta {",
368
+ " auth?: MiddlewareOptions",
369
+ " }",
370
+ " }",
371
+ "export {}"
372
+ ].join("\n");
373
+ },
374
+ write: true
375
+ });
151
376
  addPlugin(resolver.resolve("./runtime/plugin"));
152
377
  }
153
378
  });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("#app").RouteMiddleware;
2
+ export default _default;
@@ -0,0 +1,31 @@
1
+ import { defu } from "defu";
2
+ import { defineNuxtRouteMiddleware, navigateTo } from "#app";
3
+ import { useUserSession } from "#imports";
4
+ export default defineNuxtRouteMiddleware(async (to) => {
5
+ if (to.meta?.auth === false) {
6
+ return;
7
+ }
8
+ const { loggedIn, options, fetchSession, session } = useUserSession();
9
+ const { only, redirectUserTo, redirectGuestTo, redirectUnauthorizedTo } = defu(to.meta.auth, options);
10
+ await fetchSession();
11
+ if (only === "guest" && loggedIn.value) {
12
+ if (to.path === redirectUserTo) {
13
+ return;
14
+ }
15
+ return navigateTo(redirectUserTo);
16
+ }
17
+ if (only && only !== "guest" && !loggedIn.value) {
18
+ if (to.path === redirectGuestTo)
19
+ return;
20
+ return navigateTo(redirectGuestTo);
21
+ }
22
+ if (only && only !== "guest" && loggedIn.value && session.value) {
23
+ const userRole = session.value.role || "user";
24
+ const requiredRoles = Array.isArray(only) ? only : [only];
25
+ if (!requiredRoles.includes(userRole) && !requiredRoles.includes("user")) {
26
+ if (to.path === redirectUnauthorizedTo)
27
+ return;
28
+ return navigateTo(redirectUnauthorizedTo ?? "/401");
29
+ }
30
+ }
31
+ });
@@ -1,2 +1,2 @@
1
- declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
1
+ declare const _default: import("#app").Plugin<Record<string, unknown>> & import("#app").ObjectPlugin<Record<string, unknown>>;
2
2
  export default _default;
@@ -1,5 +1,5 @@
1
1
  import { defineEventHandler, toWebRequest } from "h3";
2
- import { auth } from "#better-auth-configs";
2
+ import { auth } from "#better-auth/server";
3
3
  export default defineEventHandler((event) => {
4
4
  return auth.handler(toWebRequest(event));
5
5
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "better-auth-nuxt",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Better Auth Nuxt Module",
5
5
  "repository": "productdevbook/better-auth-nuxt",
6
6
  "license": "MIT",
@@ -52,6 +52,7 @@
52
52
  "@nuxt/module-builder": "^1.0.1",
53
53
  "@nuxt/schema": "^3.16.2",
54
54
  "@nuxt/test-utils": "^3.17.2",
55
+ "@tailwindcss/vite": "^4.1.4",
55
56
  "@types/better-sqlite3": "^7.6.13",
56
57
  "@types/node": "latest",
57
58
  "better-auth": "^1.2.7",