@lenne.tech/nuxt-extensions 1.5.1 → 1.5.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/CLAUDE.md +115 -0
- package/dist/module.d.mts +1 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +1 -1
- package/dist/runtime/lib/auth-client.d.ts +2 -2
- package/dist/runtime/middleware/setup.d.ts +2 -1
- package/dist/runtime/plugins/error-translation.client.d.ts +2 -1
- package/package.json +30 -19
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# @lenne.tech/nuxt-extensions
|
|
2
|
+
|
|
3
|
+
Reusable Nuxt 4 module providing composables, components, utilities, and Better Auth integration for lenne.tech projects.
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
src/
|
|
9
|
+
├── module.ts # Nuxt module entry point (auto-imports, plugin registration)
|
|
10
|
+
├── runtime/
|
|
11
|
+
│ ├── composables/ # Auto-imported composables
|
|
12
|
+
│ ├── components/ # Auto-imported components
|
|
13
|
+
│ ├── lib/ # Library exports (auth-client, helpers)
|
|
14
|
+
│ ├── middleware/ # Route middleware (auth)
|
|
15
|
+
│ ├── plugins/ # Nuxt plugins (auth initialization)
|
|
16
|
+
│ ├── server/ # Nitro server routes (auth proxy)
|
|
17
|
+
│ ├── testing/ # Playwright test helpers
|
|
18
|
+
│ ├── types/ # TypeScript type definitions
|
|
19
|
+
│ └── utils/ # Auto-imported utility functions
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Key Composables
|
|
23
|
+
|
|
24
|
+
| Composable | Purpose |
|
|
25
|
+
|-----------|---------|
|
|
26
|
+
| `useBetterAuth()` | Authentication state, login, logout, session management |
|
|
27
|
+
| `useAuthClient()` | Raw Better Auth client access |
|
|
28
|
+
| `useTusUpload()` | TUS resumable file uploads |
|
|
29
|
+
|
|
30
|
+
## Module Configuration
|
|
31
|
+
|
|
32
|
+
Configure in `nuxt.config.ts`:
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
export default defineNuxtConfig({
|
|
36
|
+
modules: ['@lenne.tech/nuxt-extensions'],
|
|
37
|
+
lennetech: {
|
|
38
|
+
// API base URL for auth proxy
|
|
39
|
+
apiUrl: 'http://localhost:3000',
|
|
40
|
+
// Enable/disable features
|
|
41
|
+
betterAuth: true,
|
|
42
|
+
tusUpload: true,
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Authentication (Better Auth)
|
|
48
|
+
|
|
49
|
+
- SSR-safe session management via `useBetterAuth()`
|
|
50
|
+
- Auth proxy server route at `/api/auth/**` (proxies to backend)
|
|
51
|
+
- Middleware `auth` for protected routes
|
|
52
|
+
- Passkey (WebAuthn) support via `@better-auth/passkey` peer dependency
|
|
53
|
+
- 2FA (TOTP) support built-in
|
|
54
|
+
|
|
55
|
+
### Auth Flow
|
|
56
|
+
|
|
57
|
+
1. Frontend calls `useBetterAuth().signIn()` / `.signUp()`
|
|
58
|
+
2. Request goes through Nitro proxy at `/api/auth/**`
|
|
59
|
+
3. Proxy forwards to backend Better Auth endpoints
|
|
60
|
+
4. Session cookie set via `httpOnly` cookie (SSR-safe)
|
|
61
|
+
|
|
62
|
+
## Testing Helpers
|
|
63
|
+
|
|
64
|
+
Import from `@lenne.tech/nuxt-extensions/testing`:
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
import { createTestUser, loginTestUser } from '@lenne.tech/nuxt-extensions/testing';
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Authentication Cookie Rules
|
|
71
|
+
|
|
72
|
+
The `useLtAuth()` composable manages the `lt-auth-state` cookie for authentication state. Projects that implement custom auth middleware MUST follow these rules:
|
|
73
|
+
|
|
74
|
+
### DO:
|
|
75
|
+
- Use `useLtAuth()` for all auth state management (login, logout, session validation)
|
|
76
|
+
- In custom auth middleware, read `lt-auth-state` via `document.cookie` (client) or `useCookie('lt-auth-state')` (server) — but ONLY for reading, never writing
|
|
77
|
+
- Let `setUser()` and `clearUser()` handle all cookie mutations
|
|
78
|
+
|
|
79
|
+
### DON'T:
|
|
80
|
+
- Don't manually set `lt-auth-state` via `document.cookie` outside of `useLtAuth()`
|
|
81
|
+
- Don't call `useCookie('lt-auth-state')` with different options than `useLtAuth()` uses (`maxAge: 604800, sameSite: 'lax'`)
|
|
82
|
+
- Don't URL-decode or JSON-parse the cookie value manually on the server — `useCookie` handles this automatically
|
|
83
|
+
- Don't write to `authState.value` from custom middleware — this generates a `Set-Cookie` header in the SSR response that may overwrite the browser's cookie
|
|
84
|
+
|
|
85
|
+
### How Auth Cookies Work:
|
|
86
|
+
1. `setUser()` writes the cookie via both `useCookie().value` (for SSR sync) and `document.cookie` (for immediate availability)
|
|
87
|
+
2. On SSR, `useCookie` reads the cookie from the HTTP Cookie header, URL-decodes it, and parses the JSON
|
|
88
|
+
3. If `useLtAuth()` can't find a valid user in the cookie on the server, it initializes with `{user: null}` — this is intentional and correct
|
|
89
|
+
4. The `iam.session_token` httpOnly cookie (set by Better Auth) is the actual session identifier — `lt-auth-state` is a convenience cache for the client-side middleware
|
|
90
|
+
|
|
91
|
+
### Custom Auth Middleware Pattern:
|
|
92
|
+
```typescript
|
|
93
|
+
// CORRECT — read-only check, no cookie mutation
|
|
94
|
+
export default defineNuxtRouteMiddleware((to) => {
|
|
95
|
+
if (import.meta.client) {
|
|
96
|
+
const cookie = document.cookie.split('; ').find(r => r.startsWith('lt-auth-state='));
|
|
97
|
+
if (cookie) {
|
|
98
|
+
const value = decodeURIComponent(cookie.split('=').slice(1).join('='));
|
|
99
|
+
const state = JSON.parse(value);
|
|
100
|
+
if (state?.user) return; // Authenticated
|
|
101
|
+
}
|
|
102
|
+
} else {
|
|
103
|
+
const authCookie = useCookie<{ user: unknown } | null>('lt-auth-state');
|
|
104
|
+
if (authCookie.value?.user) return; // Authenticated
|
|
105
|
+
}
|
|
106
|
+
return navigateTo('/auth/login');
|
|
107
|
+
});
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Development Rules
|
|
111
|
+
|
|
112
|
+
1. **ALWAYS read source code** in `dist/runtime/` to understand available composables and components
|
|
113
|
+
2. **Use `useBetterAuth()`** for authentication — never implement auth manually
|
|
114
|
+
3. **Check existing composables** before creating new ones — this module may already provide what you need
|
|
115
|
+
4. **Peer dependencies** (`better-auth`, `@better-auth/passkey`, `tus-js-client`) must be installed in the consuming project
|
package/dist/module.d.mts
CHANGED
|
@@ -6,7 +6,7 @@ export { LtAuthModuleOptions, LtErrorTranslationModuleOptions, LtExtensionsModul
|
|
|
6
6
|
export { LtErrorTranslationResponse, LtParsedError, UseLtErrorTranslationReturn } from '../dist/runtime/types/error.js';
|
|
7
7
|
|
|
8
8
|
declare const name = "@lenne.tech/nuxt-extensions";
|
|
9
|
-
declare const version = "1.
|
|
9
|
+
declare const version = "1.5.2";
|
|
10
10
|
declare const configKey = "ltExtensions";
|
|
11
11
|
declare const _default: _nuxt_schema.NuxtModule<LtExtensionsModuleOptions, LtExtensionsModuleOptions, false>;
|
|
12
12
|
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineNuxtModule, createResolver, addImports, addComponent, addPlugin, addRouteMiddleware } from '@nuxt/kit';
|
|
2
2
|
|
|
3
3
|
const name = "@lenne.tech/nuxt-extensions";
|
|
4
|
-
const version = "1.
|
|
4
|
+
const version = "1.5.2";
|
|
5
5
|
const configKey = "ltExtensions";
|
|
6
6
|
const defaultOptions = {
|
|
7
7
|
auth: {
|
|
@@ -465,7 +465,7 @@ export declare function createLtAuthClient(config?: LtAuthClientConfig): {
|
|
|
465
465
|
*/
|
|
466
466
|
passkey: any;
|
|
467
467
|
social: <FetchOptions extends import("better-auth").ClientFetchOption<Partial<{
|
|
468
|
-
provider: (string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel";
|
|
468
|
+
provider: (string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat";
|
|
469
469
|
callbackURL?: string | undefined;
|
|
470
470
|
newUserCallbackURL?: string | undefined;
|
|
471
471
|
errorCallbackURL?: string | undefined;
|
|
@@ -489,7 +489,7 @@ export declare function createLtAuthClient(config?: LtAuthClientConfig): {
|
|
|
489
489
|
loginHint?: string | undefined;
|
|
490
490
|
additionalData?: Record<string, any> | undefined;
|
|
491
491
|
}> & Record<string, any>, Partial<Record<string, any>> & Record<string, any>, Record<string, any> | undefined>>(data_0: import("better-auth").Prettify<{
|
|
492
|
-
provider: (string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel";
|
|
492
|
+
provider: (string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat";
|
|
493
493
|
callbackURL?: string | undefined;
|
|
494
494
|
newUserCallbackURL?: string | undefined;
|
|
495
495
|
errorCallbackURL?: string | undefined;
|
|
@@ -8,5 +8,6 @@
|
|
|
8
8
|
* - needsSetup === true AND route != setupPath -> redirect to setupPath
|
|
9
9
|
* - needsSetup === false AND route === setupPath -> redirect to loginPath
|
|
10
10
|
*/
|
|
11
|
-
|
|
11
|
+
import type { RouteMiddleware } from "#app";
|
|
12
|
+
declare const _default: RouteMiddleware;
|
|
12
13
|
export default _default;
|
|
@@ -4,5 +4,6 @@
|
|
|
4
4
|
* Automatically loads error translations on app start.
|
|
5
5
|
* Provides global helper methods: $ltTranslateError, $ltShowErrorToast
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
import type { ObjectPlugin, Plugin } from "#app";
|
|
8
|
+
declare const _default: Plugin & ObjectPlugin;
|
|
8
9
|
export default _default;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lenne.tech/nuxt-extensions",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.3",
|
|
4
4
|
"description": "Reusable Nuxt 4 composables, components, and Better-Auth integration for lenne.tech projects",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
},
|
|
13
13
|
"author": "lenne.Tech <info@lenne.tech> (https://lenne.tech)",
|
|
14
14
|
"license": "MIT",
|
|
15
|
-
"packageManager": "pnpm@10.
|
|
15
|
+
"packageManager": "pnpm@10.33.0",
|
|
16
16
|
"type": "module",
|
|
17
17
|
"exports": {
|
|
18
18
|
".": {
|
|
@@ -43,7 +43,8 @@
|
|
|
43
43
|
}
|
|
44
44
|
},
|
|
45
45
|
"files": [
|
|
46
|
-
"dist"
|
|
46
|
+
"dist",
|
|
47
|
+
"CLAUDE.md"
|
|
47
48
|
],
|
|
48
49
|
"scripts": {
|
|
49
50
|
"prepare": "git config core.hooksPath .githooks",
|
|
@@ -93,22 +94,22 @@
|
|
|
93
94
|
}
|
|
94
95
|
},
|
|
95
96
|
"devDependencies": {
|
|
96
|
-
"@better-auth/passkey": "1.5.
|
|
97
|
-
"@nuxt/devtools": "3.2.
|
|
97
|
+
"@better-auth/passkey": "1.5.6",
|
|
98
|
+
"@nuxt/devtools": "3.2.4",
|
|
98
99
|
"@nuxt/module-builder": "1.0.2",
|
|
99
100
|
"@nuxt/schema": "4.4.2",
|
|
100
|
-
"@playwright/test": "1.
|
|
101
|
-
"@types/node": "25.5.
|
|
102
|
-
"@vitest/coverage-v8": "4.1.
|
|
103
|
-
"better-auth": "1.5.
|
|
104
|
-
"happy-dom": "20.8.
|
|
101
|
+
"@playwright/test": "1.59.1",
|
|
102
|
+
"@types/node": "25.5.2",
|
|
103
|
+
"@vitest/coverage-v8": "4.1.2",
|
|
104
|
+
"better-auth": "1.5.6",
|
|
105
|
+
"happy-dom": "20.8.9",
|
|
105
106
|
"nuxt": "4.4.2",
|
|
106
|
-
"oxfmt": "0.
|
|
107
|
-
"oxlint": "1.
|
|
107
|
+
"oxfmt": "0.43.0",
|
|
108
|
+
"oxlint": "1.58.0",
|
|
108
109
|
"tus-js-client": "4.3.1",
|
|
109
110
|
"typescript": "5.9.3",
|
|
110
|
-
"vitest": "4.1.
|
|
111
|
-
"vue-tsc": "3.2.
|
|
111
|
+
"vitest": "4.1.2",
|
|
112
|
+
"vue-tsc": "3.2.6"
|
|
112
113
|
},
|
|
113
114
|
"pnpm": {
|
|
114
115
|
"onlyBuiltDependencies": [
|
|
@@ -116,13 +117,23 @@
|
|
|
116
117
|
"esbuild"
|
|
117
118
|
],
|
|
118
119
|
"overrides": {
|
|
119
|
-
"
|
|
120
|
-
"
|
|
121
|
-
"
|
|
120
|
+
"brace-expansion@<2.0.3": ">=2.0.3",
|
|
121
|
+
"brace-expansion@>=4.0.0 <5.0.5": ">=5.0.5",
|
|
122
|
+
"defu@<=6.1.4": ">=6.1.5",
|
|
123
|
+
"h3@<1.15.9": ">=1.15.9",
|
|
124
|
+
"lodash@<=4.17.23": ">=4.18.0",
|
|
125
|
+
"minimatch@>=5.0.0 <5.1.9": "5.1.9",
|
|
126
|
+
"minimatch@>=9.0.0 <9.0.9": "9.0.9",
|
|
127
|
+
"minimatch@>=10.0.0 <10.2.5": "10.2.5",
|
|
128
|
+
"node-forge@<1.4.0": ">=1.4.0",
|
|
129
|
+
"picomatch@<2.3.2": ">=2.3.2",
|
|
130
|
+
"picomatch@>=4.0.0 <4.0.4": ">=4.0.4",
|
|
122
131
|
"rollup@>=4.0.0 <4.59.0": ">=4.59.0",
|
|
123
|
-
"serialize-javascript
|
|
132
|
+
"serialize-javascript@<7.0.5": ">=7.0.5",
|
|
133
|
+
"srvx@<0.11.13": ">=0.11.13",
|
|
124
134
|
"svgo@=4.0.0": ">=4.0.1",
|
|
125
|
-
"tar@<7.5.11": "7.5.11"
|
|
135
|
+
"tar@<7.5.11": "7.5.11",
|
|
136
|
+
"yaml@>=2.0.0 <2.8.3": ">=2.8.3"
|
|
126
137
|
}
|
|
127
138
|
},
|
|
128
139
|
"keywords": [
|