better-auth-nuxt 0.0.2 → 0.0.3

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
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.3",
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",
@@ -50,6 +163,12 @@ const module = defineNuxtModule({
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")
@@ -113,13 +231,13 @@ const module = defineNuxtModule({
113
231
  }
114
232
  }
115
233
  }
116
- registerTemplate({
117
- filename: "better-auth-configs.mjs",
234
+ const server = registerTemplate({
235
+ filename: "better-auth/server.mjs",
118
236
  getContents: serverAuth,
119
237
  options: { configs: serverConfigs }
120
238
  });
121
239
  addTypeTemplate({
122
- filename: "better-auth-configs.d.ts",
240
+ filename: "better-auth/server.d.ts",
123
241
  getContents: () => {
124
242
  return [
125
243
  'import { betterAuth } from "better-auth"',
@@ -138,16 +256,87 @@ const module = defineNuxtModule({
138
256
  ].join("\n");
139
257
  }
140
258
  });
259
+ const clientConfigs = [];
260
+ for (const layer of nuxt.options._layers) {
261
+ const paths = await glob([
262
+ "**/*.better-auth-client.ts",
263
+ ...options.clientConfigs?.map((pattern) => {
264
+ return `**/${pattern}.ts`;
265
+ }) || []
266
+ ], { onlyFiles: true, ignore: nuxt.options.ignore, dot: true, cwd: layer.config.rootDir, absolute: true });
267
+ const pathsJS = await glob([
268
+ "**/*.better-auth.js",
269
+ ...options.serverConfigs?.map((pattern) => {
270
+ return `**/${pattern}.js`;
271
+ }) || []
272
+ ], { cwd: layer.config.serverDir });
273
+ if (paths.length === 0 && pathsJS.length === 0) {
274
+ continue;
275
+ }
276
+ for (const path of [...paths, ...pathsJS]) {
277
+ console.log("path", path);
278
+ if (fs.existsSync(path)) {
279
+ clientConfigs.push({
280
+ key: pascalCase(hash(path)),
281
+ path
282
+ });
283
+ }
284
+ }
285
+ }
286
+ const client = registerTemplate({
287
+ filename: "better-auth/client.mjs",
288
+ getContents: useUserSession,
289
+ options: { configs: clientConfigs }
290
+ });
291
+ addTypeTemplate({
292
+ filename: "better-auth/client.d.ts",
293
+ getContents: () => {
294
+ return [
295
+ 'import { createAuthInstance } from "./client.mjs"',
296
+ 'import type { ClientOptions, InferSessionFromClient, InferUserFromClient } from "better-auth"',
297
+ 'import type { RouteLocationRaw } from "vue-router"',
298
+ 'import { Ref, ComputedRef } from "vue"',
299
+ ...clientConfigs.map((config) => {
300
+ return `import ${config.key} from "${config.path}"`;
301
+ }),
302
+ "export interface RuntimeAuthConfig {",
303
+ " redirectUserTo: RouteLocationRaw | string",
304
+ " redirectGuestTo: RouteLocationRaw | string",
305
+ " redirectUnauthorizedTo: RouteLocationRaw | string",
306
+ "}",
307
+ "export interface AuthSignOutOptions {",
308
+ " redirectTo?: RouteLocationRaw",
309
+ "}",
310
+ "export type AuthClient = ReturnType<typeof createAuthInstance>",
311
+ "export declare const useUserSession: () => AuthClient"
312
+ ].join("\n");
313
+ }
314
+ });
141
315
  addServerImports([
142
316
  {
143
- from: "#better-auth-configs",
317
+ from: server.dst,
144
318
  name: "useAuth"
145
319
  },
146
320
  {
147
- from: "#better-auth-configs",
321
+ from: server.dst,
148
322
  name: "auth"
149
323
  }
150
324
  ]);
325
+ addImports([
326
+ {
327
+ from: client.dst,
328
+ name: "useUserSession"
329
+ },
330
+ {
331
+ from: client.dst,
332
+ name: "createAuthInstance"
333
+ }
334
+ ]);
335
+ addRouteMiddleware({
336
+ name: "better-auth",
337
+ path: resolver.resolve("./runtime/middleware/auth.global"),
338
+ global: true
339
+ });
151
340
  addPlugin(resolver.resolve("./runtime/plugin"));
152
341
  }
153
342
  });
@@ -0,0 +1,27 @@
1
+ type MiddlewareOptions = false | {
2
+ /**
3
+ * Only apply auth middleware to guest or user
4
+ */
5
+ only?: 'guest' | 'user' | 'member' | 'admin';
6
+ /**
7
+ * Redirect authenticated user to this route
8
+ */
9
+ redirectUserTo?: string;
10
+ /**
11
+ * Redirect guest to this route
12
+ */
13
+ redirectGuestTo?: string;
14
+ redirectUnauthorizedTo?: string;
15
+ };
16
+ declare module '#app' {
17
+ interface PageMeta {
18
+ auth?: MiddlewareOptions;
19
+ }
20
+ }
21
+ declare module 'vue-router' {
22
+ interface RouteMeta {
23
+ auth?: MiddlewareOptions;
24
+ }
25
+ }
26
+ declare const _default: import("#app").RouteMiddleware;
27
+ export default _default;
@@ -0,0 +1,35 @@
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
+ if (import.meta.client) {
11
+ await fetchSession();
12
+ }
13
+ if (loggedIn.value && to.path.startsWith("/auth/")) {
14
+ if (to.path === redirectUserTo) {
15
+ return;
16
+ }
17
+ return navigateTo(redirectUserTo);
18
+ }
19
+ if (only === "guest" && loggedIn.value) {
20
+ if (to.path === redirectUserTo) {
21
+ return;
22
+ }
23
+ return navigateTo(redirectUserTo);
24
+ }
25
+ if (only && only !== "guest" && !loggedIn.value) {
26
+ if (to.path === redirectGuestTo)
27
+ return;
28
+ return navigateTo(redirectGuestTo);
29
+ }
30
+ if (only && only !== "guest" && session.value) {
31
+ if (to.path === redirectUnauthorizedTo)
32
+ return;
33
+ return navigateTo(redirectUnauthorizedTo ?? "/401");
34
+ }
35
+ });
@@ -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.3",
4
4
  "description": "Better Auth Nuxt Module",
5
5
  "repository": "productdevbook/better-auth-nuxt",
6
6
  "license": "MIT",