@lenne.tech/nuxt-extensions 1.19.1 → 1.20.1
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 +1 -1
- package/README.md +14 -10
- package/dist/module.d.mts +3 -3
- package/dist/module.json +1 -1
- package/dist/module.mjs +1 -1
- package/dist/runtime/composables/auth/use-lt-auth.js +1 -1
- package/dist/runtime/composables/use-lt-tus-upload.js +3 -3
- package/dist/runtime/lib/auth-client.js +1 -1
- package/dist/runtime/plugins/auth-interceptor.client.js +4 -2
- package/dist/runtime/plugins/form-label-association.client.d.ts +2 -1
- package/dist/runtime/plugins/pre-hydration-input.client.d.ts +2 -1
- package/dist/runtime/testing/playwright-helpers.js +1 -1
- package/package.json +24 -23
package/CLAUDE.md
CHANGED
|
@@ -347,7 +347,7 @@ fields at `app:beforeMount` and restores them at `app:mounted`, dispatching a sy
|
|
|
347
347
|
Handling" below).
|
|
348
348
|
3. **Check existing composables** before creating new ones — this module may already provide what you need
|
|
349
349
|
4. **Peer dependencies** (`better-auth`, `@better-auth/passkey`, `tus-js-client`) must be installed in the consuming project.
|
|
350
|
-
`better-auth` and `@better-auth/passkey` are pinned to **`>=1.7.
|
|
350
|
+
`better-auth` and `@better-auth/passkey` are pinned to **`>=1.7.12 <1.8.0`** — deliberately not a caret.
|
|
351
351
|
**They move in lock-step with `@lenne.tech/nest-server`.** better-auth is one protocol with two ends;
|
|
352
352
|
this module is the client end, nest-server the server end, and both declare the *same* narrow range.
|
|
353
353
|
Raising it means raising it in **both** framework repos and pinning the new version in **both** starters,
|
package/README.md
CHANGED
|
@@ -29,8 +29,8 @@ Reusable Nuxt 4 composables, components, and Better-Auth integration for lenne.t
|
|
|
29
29
|
|---|---|---|
|
|
30
30
|
| Node | `>= 22` | |
|
|
31
31
|
| Nuxt | `^4.0.0` | |
|
|
32
|
-
| `better-auth` | `>=1.7.
|
|
33
|
-
| `@better-auth/passkey` | `>=1.7.
|
|
32
|
+
| `better-auth` | `>=1.7.12 <1.8.0` | **required peer** — pin it, see below |
|
|
33
|
+
| `@better-auth/passkey` | `>=1.7.12 <1.8.0` | optional peer, passkey/WebAuthn only |
|
|
34
34
|
| `tus-js-client` | `>=4.0.0` | optional peer, resumable uploads only |
|
|
35
35
|
| `@lenne.tech/nest-server` | `>= 11.37.0` | **only if you use the backend** — see the lock-step rule |
|
|
36
36
|
|
|
@@ -38,7 +38,7 @@ Reusable Nuxt 4 composables, components, and Better-Auth integration for lenne.t
|
|
|
38
38
|
better-auth is one protocol with two ends. This module is the client end and
|
|
39
39
|
`@lenne.tech/nest-server` is the server end, and they must resolve the **same**
|
|
40
40
|
better-auth minor. better-auth breaks in *minor* releases — 1.7 removed subpath
|
|
41
|
-
exports and changed the 2FA response shape — so a caret (`^1.7.
|
|
41
|
+
exports and changed the 2FA response shape — so a caret (`^1.7.12`) would re-open the
|
|
42
42
|
hole at 1.8. If the api and the app drift apart, 2FA activation fails at runtime with a
|
|
43
43
|
generic client error while **both** projects' checks stay green: each is internally
|
|
44
44
|
consistent, and only the assembled workspace has both halves.
|
|
@@ -46,17 +46,21 @@ consistent, and only the assembled workspace has both halves.
|
|
|
46
46
|
Raising better-auth therefore means raising it in `@lenne.tech/nest-server` **and**
|
|
47
47
|
`@lenne.tech/nuxt-extensions` in one step.
|
|
48
48
|
|
|
49
|
-
**Why the floor is 1.7.
|
|
49
|
+
**Why the floor is 1.7.12:** better-auth before 1.7.12 verifies JWTs with the algorithm named
|
|
50
|
+
in the token's own header instead of the algorithm of the stored key
|
|
51
|
+
([#11925](https://github.com/better-auth/better-auth/pull/11925)). Below 1.7.7 it is also
|
|
52
|
+
affected by
|
|
50
53
|
[GHSA-965c-763c-88jm](https://github.com/better-auth/better-auth/security/advisories/GHSA-965c-763c-88jm)
|
|
51
|
-
(critical): the OAuth state can be used as a magic link to sign in as another user.
|
|
52
|
-
|
|
54
|
+
(critical): the OAuth state can be used as a magic link to sign in as another user. Both flaws
|
|
55
|
+
are in the server end, so your API must run 1.7.12 too (`@lenne.tech/nest-server` 12.0.0
|
|
56
|
+
declares the same range), and the pin below keeps both halves on it.
|
|
53
57
|
|
|
54
58
|
## Installation
|
|
55
59
|
|
|
56
60
|
```bash
|
|
57
|
-
npm install @lenne.tech/nuxt-extensions better-auth@1.7.
|
|
61
|
+
npm install @lenne.tech/nuxt-extensions better-auth@1.7.12
|
|
58
62
|
# Optional: For passkey support
|
|
59
|
-
npm install @better-auth/passkey@1.7.
|
|
63
|
+
npm install @better-auth/passkey@1.7.12
|
|
60
64
|
# Optional: For TUS file uploads
|
|
61
65
|
npm install tus-js-client
|
|
62
66
|
```
|
|
@@ -66,8 +70,8 @@ In a fullstack monorepo, pin it workspace-wide so the api and the app cannot dri
|
|
|
66
70
|
```yaml
|
|
67
71
|
# pnpm-workspace.yaml
|
|
68
72
|
overrides:
|
|
69
|
-
better-auth: 1.7.
|
|
70
|
-
'@better-auth/passkey': 1.7.
|
|
73
|
+
better-auth: 1.7.12
|
|
74
|
+
'@better-auth/passkey': 1.7.12
|
|
71
75
|
```
|
|
72
76
|
|
|
73
77
|
## Features
|
package/dist/module.d.mts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as nuxt_schema from 'nuxt/schema';
|
|
2
2
|
import { LtExtensionsModuleOptions } from '../dist/runtime/types/index.js';
|
|
3
3
|
export * from '../dist/runtime/types/index.js';
|
|
4
4
|
|
|
5
5
|
declare const name = "@lenne.tech/nuxt-extensions";
|
|
6
|
-
declare const version = "1.
|
|
6
|
+
declare const version = "1.20.1";
|
|
7
7
|
declare const configKey = "ltExtensions";
|
|
8
8
|
declare const DEFAULT_LT_AUTH_STATE_COOKIE = "lt-auth-state";
|
|
9
9
|
declare const DEFAULT_LT_JWT_TOKEN_COOKIE = "lt-jwt-token";
|
|
10
|
-
declare const _default:
|
|
10
|
+
declare const _default: nuxt_schema.NuxtModule<LtExtensionsModuleOptions, LtExtensionsModuleOptions, false>;
|
|
11
11
|
|
|
12
12
|
export { DEFAULT_LT_AUTH_STATE_COOKIE, DEFAULT_LT_JWT_TOKEN_COOKIE, configKey, _default as default, name, version };
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { defineNuxtModule, createResolver, tryResolveModule, addImports, addComp
|
|
|
2
2
|
import { pathToFileURL } from 'node:url';
|
|
3
3
|
|
|
4
4
|
const name = "@lenne.tech/nuxt-extensions";
|
|
5
|
-
const version = "1.
|
|
5
|
+
const version = "1.20.1";
|
|
6
6
|
const configKey = "ltExtensions";
|
|
7
7
|
const DEFAULT_LT_AUTH_STATE_COOKIE = "lt-auth-state";
|
|
8
8
|
const DEFAULT_LT_JWT_TOKEN_COOKIE = "lt-jwt-token";
|
|
@@ -173,7 +173,7 @@ export function useLtTusUpload(defaultOptions = {}) {
|
|
|
173
173
|
const tusUpload = tusUploads.value.get(id);
|
|
174
174
|
if (item && tusUpload && item.status !== "uploading") {
|
|
175
175
|
updateItem(id, { startedAt: /* @__PURE__ */ new Date(), status: "uploading" });
|
|
176
|
-
tusUpload.findPreviousUploads().then((previousUploads) => {
|
|
176
|
+
void tusUpload.findPreviousUploads().then((previousUploads) => {
|
|
177
177
|
const previousUpload = previousUploads[0];
|
|
178
178
|
if (previousUpload) {
|
|
179
179
|
tusUpload.resumeFromPreviousUpload(previousUpload);
|
|
@@ -191,7 +191,7 @@ export function useLtTusUpload(defaultOptions = {}) {
|
|
|
191
191
|
function pauseUpload(id) {
|
|
192
192
|
const tusUpload = tusUploads.value.get(id);
|
|
193
193
|
if (tusUpload) {
|
|
194
|
-
tusUpload.abort();
|
|
194
|
+
void tusUpload.abort();
|
|
195
195
|
updateItem(id, { status: "paused" });
|
|
196
196
|
}
|
|
197
197
|
}
|
|
@@ -207,7 +207,7 @@ export function useLtTusUpload(defaultOptions = {}) {
|
|
|
207
207
|
function cancelUpload(id) {
|
|
208
208
|
const tusUpload = tusUploads.value.get(id);
|
|
209
209
|
if (tusUpload) {
|
|
210
|
-
tusUpload.abort();
|
|
210
|
+
void tusUpload.abort();
|
|
211
211
|
}
|
|
212
212
|
tusUploads.value.delete(id);
|
|
213
213
|
const newMap = new Map(uploadItems.value);
|
|
@@ -117,6 +117,8 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|
|
117
117
|
const currentPath = router?.currentRoute?.value?.fullPath;
|
|
118
118
|
const redirectQuery = currentPath && currentPath !== loginPath ? `?redirect=${encodeURIComponent(currentPath)}` : "";
|
|
119
119
|
window.location.href = loginPath + redirectQuery;
|
|
120
|
+
} catch (error) {
|
|
121
|
+
console.error("[LtAuth Interceptor] Handling a 401 failed:", error);
|
|
120
122
|
} finally {
|
|
121
123
|
if (loggingOut) {
|
|
122
124
|
setTimeout(() => {
|
|
@@ -139,7 +141,7 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|
|
139
141
|
options.onResponseError(context);
|
|
140
142
|
}
|
|
141
143
|
if (context.response?.status === 401) {
|
|
142
|
-
handleUnauthorized(url);
|
|
144
|
+
void handleUnauthorized(url);
|
|
143
145
|
}
|
|
144
146
|
}
|
|
145
147
|
});
|
|
@@ -149,7 +151,7 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|
|
149
151
|
const response = await originalNativeFetch(input, init);
|
|
150
152
|
if (response.status === 401) {
|
|
151
153
|
const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
152
|
-
handleUnauthorized(url);
|
|
154
|
+
void handleUnauthorized(url);
|
|
153
155
|
}
|
|
154
156
|
return response;
|
|
155
157
|
};
|
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
*
|
|
67
67
|
* Default on; opt out with `ltExtensions.formLabelAssociation.enabled: false`.
|
|
68
68
|
*/
|
|
69
|
+
import type { ObjectPlugin, Plugin } from '#app';
|
|
69
70
|
/**
|
|
70
71
|
* Re-point every dangling field label at the control in its own field.
|
|
71
72
|
*
|
|
@@ -123,5 +124,5 @@ export declare function repairFieldAssociations(root: Document | ParentNode): {
|
|
|
123
124
|
groups: number;
|
|
124
125
|
labels: number;
|
|
125
126
|
};
|
|
126
|
-
declare const _default:
|
|
127
|
+
declare const _default: Plugin & ObjectPlugin;
|
|
127
128
|
export default _default;
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
* browsers do not raise the on-screen keyboard for it. Preserving the entry avoids all of
|
|
52
52
|
* that, because the field is never anything other than a normal, editable field.
|
|
53
53
|
*/
|
|
54
|
+
import type { ObjectPlugin, Plugin } from '#app';
|
|
54
55
|
type EditableField = HTMLInputElement | HTMLTextAreaElement;
|
|
55
56
|
/**
|
|
56
57
|
* Collect fields the user edited before hydration.
|
|
@@ -67,5 +68,5 @@ export declare function collectEditedFields(root: ParentNode): Map<EditableField
|
|
|
67
68
|
* @returns `true` when a value was actually restored.
|
|
68
69
|
*/
|
|
69
70
|
export declare function restoreField(field: EditableField, value: string): boolean;
|
|
70
|
-
declare const _default:
|
|
71
|
+
declare const _default: Plugin & ObjectPlugin;
|
|
71
72
|
export default _default;
|
|
@@ -114,7 +114,7 @@ export async function waitForElement(page, selector, options = {}) {
|
|
|
114
114
|
resolve();
|
|
115
115
|
return;
|
|
116
116
|
}
|
|
117
|
-
Promise.
|
|
117
|
+
void Promise.allSettled(el.getAnimations().map((a) => a.finished)).then(() => resolve());
|
|
118
118
|
});
|
|
119
119
|
});
|
|
120
120
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lenne.tech/nuxt-extensions",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.20.1",
|
|
4
4
|
"description": "Reusable Nuxt 4 composables, components, and Better-Auth integration for lenne.tech projects",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -51,17 +51,17 @@
|
|
|
51
51
|
"prepack": "node scripts/sync-module-version.mjs && nuxt-module-build build",
|
|
52
52
|
"c": "pnpm run check",
|
|
53
53
|
"check": "node scripts/check.mjs",
|
|
54
|
-
"check:raw": "pnpm install --frozen-lockfile && pnpm audit && pnpm run check:suppressions && pnpm peers check && pnpm run format:check && pnpm run
|
|
55
|
-
"check:fix": "pnpm install && pnpm audit --fix && pnpm run check:suppressions && pnpm peers check && pnpm run format && pnpm run lint:fix && pnpm run version:sync && pnpm test:types && pnpm test && pnpm run build && pnpm run check:manifest",
|
|
56
|
-
"check:naf": "pnpm install && pnpm peers check && pnpm run format && pnpm run lint:fix && pnpm run version:sync && pnpm test:types && pnpm test && pnpm run build && pnpm run check:manifest",
|
|
54
|
+
"check:raw": "pnpm install --frozen-lockfile && pnpm audit && pnpm run check:suppressions && pnpm peers check && pnpm run format:check && pnpm run dev:prepare && pnpm run lint && pnpm run version:check && pnpm test:types && pnpm test && pnpm run build && pnpm run check:manifest",
|
|
55
|
+
"check:fix": "pnpm install && pnpm audit --fix && pnpm run check:suppressions && pnpm peers check && pnpm run format && pnpm run dev:prepare && pnpm run lint:fix && pnpm run version:sync && pnpm test:types && pnpm test && pnpm run build && pnpm run check:manifest",
|
|
56
|
+
"check:naf": "pnpm install && pnpm peers check && pnpm run format && pnpm run dev:prepare && pnpm run lint:fix && pnpm run version:sync && pnpm test:types && pnpm test && pnpm run build && pnpm run check:manifest",
|
|
57
57
|
"cf": "pnpm run check:fix",
|
|
58
58
|
"cnaf": "pnpm run check:naf",
|
|
59
59
|
"dev": "pnpm dev:prepare && nuxt dev playground",
|
|
60
60
|
"dev:build": "nuxt build playground",
|
|
61
61
|
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxt prepare playground",
|
|
62
62
|
"build": "nuxt-module-build build",
|
|
63
|
-
"lint": "oxlint src/ scripts/",
|
|
64
|
-
"lint:fix": "oxlint --fix src/ scripts/",
|
|
63
|
+
"lint": "oxlint --type-aware src/ scripts/",
|
|
64
|
+
"lint:fix": "oxlint --type-aware --fix src/ scripts/",
|
|
65
65
|
"format": "oxfmt --write src/",
|
|
66
66
|
"format:check": "oxfmt --check src/",
|
|
67
67
|
"version:sync": "node scripts/sync-module-version.mjs",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"test:watch": "vitest watch",
|
|
71
71
|
"test:coverage": "vitest run --coverage",
|
|
72
72
|
"test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit",
|
|
73
|
-
"release": "pnpm format:check && pnpm lint && pnpm run version:check && pnpm test:types && pnpm test && pnpm run check:consumer && pnpm prepack",
|
|
73
|
+
"release": "pnpm format:check && pnpm run dev:prepare && pnpm lint && pnpm run version:check && pnpm test:types && pnpm test && pnpm run check:consumer && pnpm prepack",
|
|
74
74
|
"check:consumer": "node scripts/check-consumer-build.mjs",
|
|
75
75
|
"check:manifest": "node scripts/check-package-manifest.mjs",
|
|
76
76
|
"check:suppressions": "node scripts/check-suppressions.mjs"
|
|
@@ -79,9 +79,9 @@
|
|
|
79
79
|
"@nuxt/kit": "^4.0.0"
|
|
80
80
|
},
|
|
81
81
|
"peerDependencies": {
|
|
82
|
-
"@better-auth/passkey": ">=1.7.
|
|
82
|
+
"@better-auth/passkey": ">=1.7.12 <1.8.0",
|
|
83
83
|
"@playwright/test": ">=1.0.0",
|
|
84
|
-
"better-auth": ">=1.7.
|
|
84
|
+
"better-auth": ">=1.7.12 <1.8.0",
|
|
85
85
|
"nuxt": "^4.0.0",
|
|
86
86
|
"tus-js-client": ">=4.0.0"
|
|
87
87
|
},
|
|
@@ -100,24 +100,25 @@
|
|
|
100
100
|
}
|
|
101
101
|
},
|
|
102
102
|
"devDependencies": {
|
|
103
|
-
"@better-auth/passkey": "1.7.
|
|
103
|
+
"@better-auth/passkey": "1.7.12",
|
|
104
104
|
"@nuxt/module-builder": "1.0.3",
|
|
105
|
-
"@nuxt/schema": "4.6.
|
|
106
|
-
"@nuxt/ui": "4.
|
|
107
|
-
"@playwright/test": "1.64.
|
|
105
|
+
"@nuxt/schema": "4.6.3",
|
|
106
|
+
"@nuxt/ui": "4.12.0",
|
|
107
|
+
"@playwright/test": "1.64.1",
|
|
108
108
|
"@types/node": "26.6.5",
|
|
109
|
-
"@vitest/coverage-v8": "5.0.
|
|
110
|
-
"@vue/server-renderer": "3.5.
|
|
111
|
-
"better-auth": "1.7.
|
|
109
|
+
"@vitest/coverage-v8": "5.0.5",
|
|
110
|
+
"@vue/server-renderer": "3.5.44",
|
|
111
|
+
"better-auth": "1.7.12",
|
|
112
112
|
"cross-spawn": "7.0.6",
|
|
113
|
-
"happy-dom": "
|
|
114
|
-
"nuxt": "4.6.
|
|
115
|
-
"oxfmt": "0.
|
|
116
|
-
"oxlint": "1.
|
|
117
|
-
"
|
|
113
|
+
"happy-dom": "21.0.4",
|
|
114
|
+
"nuxt": "4.6.3",
|
|
115
|
+
"oxfmt": "0.75.0",
|
|
116
|
+
"oxlint": "1.90.0",
|
|
117
|
+
"oxlint-tsgolint": "7.0.2005",
|
|
118
|
+
"reka-ui": "2.11.0",
|
|
118
119
|
"tus-js-client": "4.3.1",
|
|
119
120
|
"typescript": "5.9.3",
|
|
120
|
-
"vitest": "5.0.
|
|
121
|
+
"vitest": "5.0.5",
|
|
121
122
|
"vue-tsc": "3.3.13"
|
|
122
123
|
},
|
|
123
124
|
"keywords": [
|
|
@@ -137,5 +138,5 @@
|
|
|
137
138
|
"node": ">= 22",
|
|
138
139
|
"pnpm": "^11.0.0"
|
|
139
140
|
},
|
|
140
|
-
"packageManager": "pnpm@11.28.
|
|
141
|
+
"packageManager": "pnpm@11.28.9+sha512.35421cea2720eca3f5ad722b67e8ef18f4d3cd4745ed2fcfeb0dc288d4e9437fad3870d91ee6e83f268f0f6f7e0f62723317b19617bb45ee4333172ef51159f8"
|
|
141
142
|
}
|