@lenne.tech/nuxt-extensions 1.2.6 → 1.2.8
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/runtime/composables/auth/use-lt-auth.js +47 -21
- package/dist/runtime/composables/use-lt-auth-client.js +2 -17
- package/dist/runtime/lib/auth-client.d.ts +21 -15
- package/dist/runtime/lib/auth-state.d.ts +1 -1
- package/dist/runtime/lib/auth-state.js +5 -1
- package/dist/runtime/types/auth.d.ts +3 -1
- package/package.json +16 -16
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
import { useNuxtApp,
|
|
1
|
+
import { useNuxtApp, useCookie, useState, ref, computed, watch } from "#imports";
|
|
2
2
|
import { ltArrayBufferToBase64Url, ltBase64UrlToUint8Array } from "../../utils/crypto.js";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
function getAuthClient() {
|
|
6
|
-
if (!_authClient) {
|
|
7
|
-
_authClient = createLtAuthClient();
|
|
8
|
-
}
|
|
9
|
-
return _authClient;
|
|
10
|
-
}
|
|
3
|
+
import { getLtApiBase } from "../../lib/auth-state.js";
|
|
4
|
+
import { useLtAuthClient } from "../use-lt-auth-client.js";
|
|
11
5
|
function useTranslation() {
|
|
12
6
|
const nuxtApp = useNuxtApp();
|
|
13
7
|
const i18n = nuxtApp.$i18n;
|
|
@@ -19,7 +13,7 @@ function useTranslation() {
|
|
|
19
13
|
};
|
|
20
14
|
}
|
|
21
15
|
export function useLtAuth() {
|
|
22
|
-
const authClient =
|
|
16
|
+
const authClient = useLtAuthClient();
|
|
23
17
|
const t = useTranslation();
|
|
24
18
|
const authState = useCookie("lt-auth-state", {
|
|
25
19
|
maxAge: 60 * 60 * 24 * 7,
|
|
@@ -57,14 +51,11 @@ export function useLtAuth() {
|
|
|
57
51
|
const isAuthenticated = computed(() => !!user.value);
|
|
58
52
|
const isAdmin = computed(() => user.value?.role === "admin");
|
|
59
53
|
const is2FAEnabled = computed(() => user.value?.twoFactorEnabled ?? false);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const basePath = config?.basePath || "/iam";
|
|
66
|
-
return isDev ? `/api${basePath}` : `${baseURL}${basePath}`;
|
|
67
|
-
}
|
|
54
|
+
const features = useState(
|
|
55
|
+
"lt-auth-features",
|
|
56
|
+
() => ({})
|
|
57
|
+
);
|
|
58
|
+
const featuresFetched = useState("lt-auth-features-fetched", () => false);
|
|
68
59
|
function setUser(userData, mode = "cookie") {
|
|
69
60
|
const newState = { user: userData, authMode: mode };
|
|
70
61
|
authState.value = newState;
|
|
@@ -98,7 +89,7 @@ export function useLtAuth() {
|
|
|
98
89
|
}
|
|
99
90
|
async function switchToJwtMode() {
|
|
100
91
|
try {
|
|
101
|
-
const apiBase =
|
|
92
|
+
const apiBase = getLtApiBase();
|
|
102
93
|
const response = await fetch(`${apiBase}/token`, {
|
|
103
94
|
method: "GET",
|
|
104
95
|
credentials: "include"
|
|
@@ -184,6 +175,21 @@ export function useLtAuth() {
|
|
|
184
175
|
return !!authState.value?.user;
|
|
185
176
|
}
|
|
186
177
|
}
|
|
178
|
+
async function fetchFeatures() {
|
|
179
|
+
try {
|
|
180
|
+
const apiBase = getLtApiBase();
|
|
181
|
+
const result = await $fetch(
|
|
182
|
+
`${apiBase}/features`
|
|
183
|
+
);
|
|
184
|
+
if (result) {
|
|
185
|
+
features.value = result;
|
|
186
|
+
featuresFetched.value = true;
|
|
187
|
+
}
|
|
188
|
+
return features.value;
|
|
189
|
+
} catch {
|
|
190
|
+
return features.value;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
187
193
|
const signIn = {
|
|
188
194
|
...authClient.signIn,
|
|
189
195
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -249,7 +255,7 @@ export function useLtAuth() {
|
|
|
249
255
|
async function authenticateWithPasskey() {
|
|
250
256
|
isLoading.value = true;
|
|
251
257
|
try {
|
|
252
|
-
const apiBase =
|
|
258
|
+
const apiBase = getLtApiBase();
|
|
253
259
|
const optionsResponse = await fetchWithAuth(
|
|
254
260
|
`${apiBase}/passkey/generate-authenticate-options`,
|
|
255
261
|
{
|
|
@@ -310,6 +316,19 @@ export function useLtAuth() {
|
|
|
310
316
|
if (authState.value) {
|
|
311
317
|
authState.value = { ...authState.value, authMode: "jwt" };
|
|
312
318
|
}
|
|
319
|
+
try {
|
|
320
|
+
const sessionResponse = await fetchWithAuth(`${apiBase}/get-session`, { method: "GET" });
|
|
321
|
+
if (sessionResponse.ok) {
|
|
322
|
+
const sessionData = await sessionResponse.json();
|
|
323
|
+
if (sessionData?.user) {
|
|
324
|
+
result.user = sessionData.user;
|
|
325
|
+
setUser(sessionData.user, "cookie");
|
|
326
|
+
switchToJwtMode().catch(() => {
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
} catch {
|
|
331
|
+
}
|
|
313
332
|
}
|
|
314
333
|
return { success: true, user: result.user, session: result.session };
|
|
315
334
|
} catch (err) {
|
|
@@ -330,7 +349,7 @@ export function useLtAuth() {
|
|
|
330
349
|
async function registerPasskey(name) {
|
|
331
350
|
isLoading.value = true;
|
|
332
351
|
try {
|
|
333
|
-
const apiBase =
|
|
352
|
+
const apiBase = getLtApiBase();
|
|
334
353
|
const optionsResponse = await fetchWithAuth(`${apiBase}/passkey/generate-register-options`, {
|
|
335
354
|
method: "GET"
|
|
336
355
|
});
|
|
@@ -429,6 +448,10 @@ export function useLtAuth() {
|
|
|
429
448
|
isLoading.value = false;
|
|
430
449
|
}
|
|
431
450
|
}
|
|
451
|
+
if (import.meta.client && !featuresFetched.value) {
|
|
452
|
+
featuresFetched.value = true;
|
|
453
|
+
fetchFeatures();
|
|
454
|
+
}
|
|
432
455
|
return {
|
|
433
456
|
// Auth state
|
|
434
457
|
authMode,
|
|
@@ -439,6 +462,9 @@ export function useLtAuth() {
|
|
|
439
462
|
// User properties
|
|
440
463
|
is2FAEnabled,
|
|
441
464
|
isAdmin,
|
|
465
|
+
// Feature detection
|
|
466
|
+
features: computed(() => features.value),
|
|
467
|
+
fetchFeatures,
|
|
442
468
|
// Auth actions
|
|
443
469
|
authenticateWithPasskey,
|
|
444
470
|
changePassword: authClient.changePassword,
|
|
@@ -3,30 +3,15 @@ import {
|
|
|
3
3
|
getOrCreateLtAuthClient,
|
|
4
4
|
resetLtAuthClientSingleton
|
|
5
5
|
} from "../lib/auth-client.js";
|
|
6
|
+
import { isLtDevMode } from "../lib/auth-state.js";
|
|
6
7
|
export function resetLtAuthClient() {
|
|
7
8
|
resetLtAuthClientSingleton();
|
|
8
9
|
}
|
|
9
|
-
function isDevMode() {
|
|
10
|
-
if (import.meta.server) {
|
|
11
|
-
return process.env.NODE_ENV !== "production";
|
|
12
|
-
}
|
|
13
|
-
if (typeof window !== "undefined") {
|
|
14
|
-
const buildId = window.__NUXT__?.config?.app?.buildId;
|
|
15
|
-
if (buildId === "dev") {
|
|
16
|
-
return true;
|
|
17
|
-
}
|
|
18
|
-
const hostname = window.location?.hostname;
|
|
19
|
-
if (hostname === "localhost" || hostname === "127.0.0.1") {
|
|
20
|
-
return true;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
10
|
export function useLtAuthClient() {
|
|
26
11
|
try {
|
|
27
12
|
const nuxtApp = useNuxtApp();
|
|
28
13
|
const config = nuxtApp.$config?.public?.ltExtensions?.auth || {};
|
|
29
|
-
const isDev =
|
|
14
|
+
const isDev = isLtDevMode();
|
|
30
15
|
let basePath = config.basePath || "/iam";
|
|
31
16
|
if (isDev && basePath && !basePath.startsWith("/api")) {
|
|
32
17
|
basePath = `/api${basePath}`;
|
|
@@ -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
|
-
|
|
727
|
+
providerId: string;
|
|
728
|
+
accountId: string;
|
|
723
729
|
}[], {
|
|
724
730
|
code?: string | undefined;
|
|
725
731
|
message?: string | undefined;
|
|
@@ -40,7 +40,7 @@ export declare function setLtAuthMode(mode: LtAuthMode): void;
|
|
|
40
40
|
/**
|
|
41
41
|
* Get the API base URL from runtime config
|
|
42
42
|
*
|
|
43
|
-
* @param basePath - The auth API base path (default: '/iam')
|
|
43
|
+
* @param basePath - The auth API base path. If not provided, reads from runtime config (default: '/iam')
|
|
44
44
|
*/
|
|
45
45
|
export declare function getLtApiBase(basePath?: string): string;
|
|
46
46
|
/**
|
|
@@ -68,7 +68,11 @@ export function setLtAuthMode(mode) {
|
|
|
68
68
|
} catch {
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
-
export function getLtApiBase(basePath
|
|
71
|
+
export function getLtApiBase(basePath) {
|
|
72
|
+
if (!basePath && typeof window !== "undefined") {
|
|
73
|
+
basePath = window.__NUXT__?.config?.public?.ltExtensions?.auth?.basePath;
|
|
74
|
+
}
|
|
75
|
+
basePath = basePath || "/iam";
|
|
72
76
|
const isDev = isLtDevMode();
|
|
73
77
|
if (isDev) {
|
|
74
78
|
return `/api${basePath}`;
|
|
@@ -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.
|
|
3
|
+
"version": "1.2.8",
|
|
4
4
|
"description": "Reusable Nuxt 4 composables, components, and Better-Auth integration for lenne.tech projects",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxt prepare playground",
|
|
54
54
|
"build": "nuxt-module-build build",
|
|
55
55
|
"lint": "oxlint src/",
|
|
56
|
-
"lint:fix": "oxlint --fix src/",
|
|
56
|
+
"lint:fix": "oxlint --fix --fix-suggestions src/",
|
|
57
57
|
"format": "oxfmt --write src/",
|
|
58
58
|
"format:check": "oxfmt --check src/",
|
|
59
59
|
"test": "vitest run",
|
|
@@ -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.
|
|
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.
|
|
90
|
+
"@better-auth/passkey": "1.4.18",
|
|
91
91
|
"@nuxt/devtools": "3.1.1",
|
|
92
|
-
"@playwright/test": "1.
|
|
92
|
+
"@playwright/test": "1.58.1",
|
|
93
93
|
"@nuxt/module-builder": "1.0.2",
|
|
94
|
-
"@nuxt/schema": "4.
|
|
94
|
+
"@nuxt/schema": "4.3.0",
|
|
95
95
|
"@nuxt/test-utils": "3.23.0",
|
|
96
|
-
"@types/node": "25.0
|
|
97
|
-
"@vitest/coverage-v8": "
|
|
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.
|
|
100
|
-
"happy-dom": "20.
|
|
101
|
-
"nuxt": "4.
|
|
102
|
-
"oxfmt": "0.
|
|
103
|
-
"oxlint": "
|
|
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.
|
|
107
|
-
"vue-tsc": "3.2.
|
|
106
|
+
"vitest": "4.0.18",
|
|
107
|
+
"vue-tsc": "3.2.4"
|
|
108
108
|
},
|
|
109
109
|
"keywords": [
|
|
110
110
|
"nuxt",
|
|
@@ -119,4 +119,4 @@
|
|
|
119
119
|
"file-upload",
|
|
120
120
|
"lenne-tech"
|
|
121
121
|
]
|
|
122
|
-
}
|
|
122
|
+
}
|