@lenne.tech/nuxt-extensions 1.2.5 → 1.2.7

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.
@@ -1,4 +1,4 @@
1
- import { useNuxtApp, useRuntimeConfig, useCookie, ref, computed, watch } from "#imports";
1
+ import { useNuxtApp, useRuntimeConfig, useCookie, useState, ref, computed, watch } from "#imports";
2
2
  import { ltArrayBufferToBase64Url, ltBase64UrlToUint8Array } from "../../utils/crypto.js";
3
3
  import { createLtAuthClient } from "../../lib/auth-client.js";
4
4
  let _authClient = null;
@@ -57,6 +57,11 @@ export function useLtAuth() {
57
57
  const isAuthenticated = computed(() => !!user.value);
58
58
  const isAdmin = computed(() => user.value?.role === "admin");
59
59
  const is2FAEnabled = computed(() => user.value?.twoFactorEnabled ?? false);
60
+ const features = useState(
61
+ "lt-auth-features",
62
+ () => ({})
63
+ );
64
+ const featuresFetched = useState("lt-auth-features-fetched", () => false);
60
65
  function getApiBase() {
61
66
  const isDev = import.meta.dev;
62
67
  const runtimeConfig = useRuntimeConfig();
@@ -184,6 +189,21 @@ export function useLtAuth() {
184
189
  return !!authState.value?.user;
185
190
  }
186
191
  }
192
+ async function fetchFeatures() {
193
+ try {
194
+ const apiBase = getApiBase();
195
+ const result = await $fetch(
196
+ `${apiBase}/features`
197
+ );
198
+ if (result) {
199
+ features.value = result;
200
+ featuresFetched.value = true;
201
+ }
202
+ return features.value;
203
+ } catch {
204
+ return features.value;
205
+ }
206
+ }
187
207
  const signIn = {
188
208
  ...authClient.signIn,
189
209
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -310,6 +330,19 @@ export function useLtAuth() {
310
330
  if (authState.value) {
311
331
  authState.value = { ...authState.value, authMode: "jwt" };
312
332
  }
333
+ try {
334
+ const sessionResponse = await fetchWithAuth(`${apiBase}/get-session`, { method: "GET" });
335
+ if (sessionResponse.ok) {
336
+ const sessionData = await sessionResponse.json();
337
+ if (sessionData?.user) {
338
+ result.user = sessionData.user;
339
+ setUser(sessionData.user, "cookie");
340
+ switchToJwtMode().catch(() => {
341
+ });
342
+ }
343
+ }
344
+ } catch {
345
+ }
313
346
  }
314
347
  return { success: true, user: result.user, session: result.session };
315
348
  } catch (err) {
@@ -429,6 +462,10 @@ export function useLtAuth() {
429
462
  isLoading.value = false;
430
463
  }
431
464
  }
465
+ if (import.meta.client && !featuresFetched.value) {
466
+ featuresFetched.value = true;
467
+ fetchFeatures();
468
+ }
432
469
  return {
433
470
  // Auth state
434
471
  authMode,
@@ -439,6 +476,9 @@ export function useLtAuth() {
439
476
  // User properties
440
477
  is2FAEnabled,
441
478
  isAdmin,
479
+ // Feature detection
480
+ features: computed(() => features.value),
481
+ fetchFeatures,
442
482
  // Auth actions
443
483
  authenticateWithPasskey,
444
484
  changePassword: authClient.changePassword,
@@ -102,6 +102,9 @@ export declare function createLtAuthClient(config?: LtAuthClientConfig): {
102
102
  readonly isPending: boolean;
103
103
  readonly isRefetching: boolean;
104
104
  readonly error: import("@better-fetch/fetch").BetterFetchError | null;
105
+ readonly refetch: (queryParams?: {
106
+ query?: import("better-auth").SessionQueryParams;
107
+ } | undefined) => Promise<void>;
105
108
  }, {
106
109
  readonly data: {
107
110
  readonly user: {
@@ -127,6 +130,9 @@ export declare function createLtAuthClient(config?: LtAuthClientConfig): {
127
130
  readonly isPending: boolean;
128
131
  readonly isRefetching: boolean;
129
132
  readonly error: import("@better-fetch/fetch").BetterFetchError | null;
133
+ readonly refetch: (queryParams?: {
134
+ query?: import("better-auth").SessionQueryParams;
135
+ } | undefined) => Promise<void>;
130
136
  }>>;
131
137
  <F extends (...args: any) => any>(useFetch: F): Promise<{
132
138
  data: import("vue").Ref<{
@@ -222,6 +228,7 @@ export declare function createLtAuthClient(config?: LtAuthClientConfig): {
222
228
  })[];
223
229
  cache?: RequestCache | undefined;
224
230
  method: string;
231
+ window?: null | undefined;
225
232
  headers?: (HeadersInit & (HeadersInit | {
226
233
  accept: "application/json" | "text/plain" | "application/octet-stream";
227
234
  "content-type": "application/json" | "text/plain" | "application/x-www-form-urlencoded" | "multipart/form-data" | "application/octet-stream";
@@ -236,7 +243,6 @@ export declare function createLtAuthClient(config?: LtAuthClientConfig): {
236
243
  referrer?: string | undefined;
237
244
  referrerPolicy?: ReferrerPolicy | undefined;
238
245
  signal?: (AbortSignal | null) | undefined;
239
- window?: null | undefined;
240
246
  onRetry?: ((response: import("@better-fetch/fetch").ResponseContext) => Promise<void> | void) | undefined;
241
247
  hookOptions?: {
242
248
  cloneResponse?: boolean;
@@ -284,25 +290,25 @@ export declare function createLtAuthClient(config?: LtAuthClientConfig): {
284
290
  token: string | null;
285
291
  user: {
286
292
  id: string;
287
- email: string;
288
- name: string;
289
- image: string | null | undefined;
290
- emailVerified: boolean;
291
293
  createdAt: Date;
292
294
  updatedAt: Date;
293
- };
295
+ email: string;
296
+ emailVerified: boolean;
297
+ name: string;
298
+ image?: string | null | undefined;
299
+ } & Record<string, any>;
294
300
  } | {
295
301
  data: {
296
302
  token: string | null;
297
303
  user: {
298
304
  id: string;
299
- email: string;
300
- name: string;
301
- image: string | null | undefined;
302
- emailVerified: boolean;
303
305
  createdAt: Date;
304
306
  updatedAt: Date;
305
- };
307
+ email: string;
308
+ emailVerified: boolean;
309
+ name: string;
310
+ image?: string | null | undefined;
311
+ } & Record<string, any>;
306
312
  };
307
313
  error: null;
308
314
  } | {
@@ -461,7 +467,7 @@ export declare function createLtAuthClient(config?: LtAuthClientConfig): {
461
467
  email: string;
462
468
  name: string;
463
469
  password: string;
464
- }, options?: any) => Promise<NonNullable<{
470
+ } & Record<string, unknown>, options?: any) => Promise<NonNullable<{
465
471
  token: null;
466
472
  user: {
467
473
  id: string;
@@ -713,13 +719,13 @@ export declare function createLtAuthClient(config?: LtAuthClientConfig): {
713
719
  query?: Record<string, any> | undefined;
714
720
  fetchOptions?: FetchOptions | undefined;
715
721
  }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<{
722
+ scopes: string[];
716
723
  id: string;
717
- providerId: string;
718
724
  createdAt: Date;
719
725
  updatedAt: Date;
720
- accountId: string;
721
726
  userId: string;
722
- scopes: string[];
727
+ providerId: string;
728
+ accountId: string;
723
729
  }[], {
724
730
  code?: string | undefined;
725
731
  message?: string | undefined;
@@ -1,7 +1,13 @@
1
1
  import { useLtAuth } from "../composables/auth/use-lt-auth.js";
2
2
  export default (nuxtApp) => {
3
3
  if (import.meta.server) return;
4
- const { clearUser, isAuthenticated } = useLtAuth();
4
+ let _authInstance = null;
5
+ function getAuth() {
6
+ if (!_authInstance) {
7
+ _authInstance = useLtAuth();
8
+ }
9
+ return _authInstance;
10
+ }
5
11
  const runtimeConfig = nuxtApp.$config?.public?.ltExtensions?.auth || {};
6
12
  const loginPath = runtimeConfig.loginPath || "/auth/login";
7
13
  const configuredPublicPaths = runtimeConfig.interceptor?.publicPaths || [];
@@ -54,6 +60,7 @@ export default (nuxtApp) => {
54
60
  }
55
61
  isHandling401 = true;
56
62
  try {
63
+ const { clearUser, isAuthenticated } = getAuth();
57
64
  if (isAuthenticated.value) {
58
65
  console.debug("[LtAuth Interceptor] Session expired, logging out...");
59
66
  clearUser();
@@ -96,6 +96,8 @@ export interface UseLtAuthReturn {
96
96
  user: ComputedRef<LtUser | null>;
97
97
  is2FAEnabled: ComputedRef<boolean>;
98
98
  isAdmin: ComputedRef<boolean>;
99
+ features: ComputedRef<Record<string, boolean | number | string[]>>;
100
+ fetchFeatures: () => Promise<Record<string, boolean | number | string[]>>;
99
101
  authenticateWithPasskey: () => Promise<LtPasskeyAuthResult>;
100
102
  changePassword: (params: {
101
103
  currentPassword: string;
@@ -120,7 +122,7 @@ export interface UseLtAuthReturn {
120
122
  email: string;
121
123
  name: string;
122
124
  password: string;
123
- }, options?: unknown) => Promise<unknown>;
125
+ } & Record<string, unknown>, options?: unknown) => Promise<unknown>;
124
126
  };
125
127
  switchToJwtMode: () => Promise<boolean>;
126
128
  validateSession: () => Promise<boolean>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenne.tech/nuxt-extensions",
3
- "version": "1.2.5",
3
+ "version": "1.2.7",
4
4
  "description": "Reusable Nuxt 4 composables, components, and Better-Auth integration for lenne.tech projects",
5
5
  "repository": {
6
6
  "type": "git",
@@ -63,7 +63,7 @@
63
63
  "release": "npm run format:check && npm run lint && npm run test:types && npm run test && npm run prepack"
64
64
  },
65
65
  "dependencies": {
66
- "@nuxt/kit": "4.2.2"
66
+ "@nuxt/kit": "4.3.0"
67
67
  },
68
68
  "peerDependencies": {
69
69
  "@better-auth/passkey": ">=1.0.0",
@@ -87,24 +87,24 @@
87
87
  }
88
88
  },
89
89
  "devDependencies": {
90
- "@better-auth/passkey": "1.4.10",
90
+ "@better-auth/passkey": "1.4.18",
91
91
  "@nuxt/devtools": "3.1.1",
92
- "@playwright/test": "1.57.0",
92
+ "@playwright/test": "1.58.1",
93
93
  "@nuxt/module-builder": "1.0.2",
94
- "@nuxt/schema": "4.2.2",
94
+ "@nuxt/schema": "4.3.0",
95
95
  "@nuxt/test-utils": "3.23.0",
96
- "@types/node": "25.0.10",
97
- "@vitest/coverage-v8": "3.0.0",
96
+ "@types/node": "25.2.0",
97
+ "@vitest/coverage-v8": "4.0.18",
98
98
  "@vue/test-utils": "2.4.6",
99
- "better-auth": "1.4.10",
100
- "happy-dom": "20.3.7",
101
- "nuxt": "4.2.2",
102
- "oxfmt": "0.26.0",
103
- "oxlint": "0.17.0",
99
+ "better-auth": "1.4.18",
100
+ "happy-dom": "20.5.0",
101
+ "nuxt": "4.3.0",
102
+ "oxfmt": "0.28.0",
103
+ "oxlint": "1.43.0",
104
104
  "tus-js-client": "4.3.1",
105
105
  "typescript": "5.9.3",
106
- "vitest": "4.0.17",
107
- "vue-tsc": "3.2.2"
106
+ "vitest": "4.0.18",
107
+ "vue-tsc": "3.2.4"
108
108
  },
109
109
  "keywords": [
110
110
  "nuxt",