@lenne.tech/nuxt-extensions 1.18.1 → 1.18.2

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
@@ -3,7 +3,7 @@ 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.18.1";
6
+ declare const version = "1.18.2";
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";
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "configKey": "ltExtensions",
3
3
  "name": "@lenne.tech/nuxt-extensions",
4
- "version": "1.18.1",
4
+ "version": "1.18.2",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.3",
7
7
  "unbuild": "3.6.1"
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.18.1";
5
+ const version = "1.18.2";
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";
@@ -2,6 +2,7 @@ import { useNuxtApp, useCookie, useState, useRequestHeaders, ref, computed, watc
2
2
  import { ltArrayBufferToBase64Url, ltBase64UrlToUint8Array } from "../../utils/crypto.js";
3
3
  import { clearLtAuthCookies, getLtApiBase, getLtAuthCookieNames, resolveLtAuthState } from "../../lib/auth-state.js";
4
4
  import { useLtAuthClient } from "../use-lt-auth-client.js";
5
+ const VALIDATE_SESSION_TIMEOUT_MS = 1e4;
5
6
  function useTranslation() {
6
7
  const nuxtApp = useNuxtApp();
7
8
  const i18n = nuxtApp.$i18n;
@@ -155,15 +156,24 @@ export function useLtAuth() {
155
156
  return merged;
156
157
  }
157
158
  async function validateSession() {
159
+ if (import.meta.server) {
160
+ return !!resolvedAuthState.value?.user;
161
+ }
158
162
  try {
159
163
  const session = authClient.useSession();
160
164
  if (session.value.isPending) {
161
165
  await new Promise((resolve) => {
162
- const unwatch = watch(
166
+ let unwatch;
167
+ const timer = setTimeout(() => {
168
+ unwatch?.();
169
+ resolve(false);
170
+ }, VALIDATE_SESSION_TIMEOUT_MS);
171
+ unwatch = watch(
163
172
  () => session.value.isPending,
164
173
  (isPending) => {
165
174
  if (!isPending) {
166
- unwatch();
175
+ clearTimeout(timer);
176
+ unwatch?.();
167
177
  resolve(true);
168
178
  }
169
179
  },
@@ -177,14 +187,14 @@ export function useLtAuth() {
177
187
  });
178
188
  return true;
179
189
  }
180
- if (authState.value?.user) {
190
+ if (resolvedAuthState.value?.user) {
181
191
  switchToJwtMode().catch(() => {
182
192
  });
183
193
  return true;
184
194
  }
185
195
  return false;
186
196
  } catch {
187
- return !!authState.value?.user;
197
+ return !!resolvedAuthState.value?.user;
188
198
  }
189
199
  }
190
200
  async function fetchFeatures() {
@@ -33,6 +33,13 @@ export declare function resetLtAuthClient(): void;
33
33
  * This ensures Docker containers can be reconfigured without rebuilding.
34
34
  * Trailing slashes are automatically stripped.
35
35
  *
36
+ * During SSR the server-only `runtimeConfig.apiUrl` (`NUXT_API_URL`) comes first,
37
+ * the same chain as `resolveLtApiBaseUrl()`. The client is built on the server
38
+ * whenever `useLtAuth()` runs in setup, and a consumer's `getSession()` from a
39
+ * middleware or `useAsyncData` goes through it. The public URL may be a name only
40
+ * the browser resolves (on Windows `*.localhost` resolves in Chromium, not in
41
+ * Node), so the server must not depend on it when an internal address is set.
42
+ *
36
43
  * ## Proxy mode (`NUXT_PUBLIC_API_PROXY=true`)
37
44
  * When enabled, `baseURL` is set to `""` (same-origin) and `basePath` is
38
45
  * prefixed with `/api` (e.g., `/api/iam`). The Vite dev proxy forwards
@@ -9,12 +9,13 @@ export function useLtAuthClient() {
9
9
  const runtimeConfig = useRuntimeConfig();
10
10
  const config = runtimeConfig.public?.ltExtensions?.auth || {};
11
11
  const publicApiUrl = String(runtimeConfig.public?.apiUrl || "");
12
+ const serverApiUrl = import.meta.server ? String(runtimeConfig.apiUrl || "") : "";
12
13
  const useProxy = isLocalDevApiProxy();
13
14
  let basePath = config.basePath || "/iam";
14
15
  if (useProxy && basePath && !basePath.startsWith("/api")) {
15
16
  basePath = `/api${basePath}`;
16
17
  }
17
- const authBaseURL = (publicApiUrl || config.baseURL || "").replace(/\/+$/, "");
18
+ const authBaseURL = (serverApiUrl || publicApiUrl || config.baseURL || "").replace(/\/+$/, "");
18
19
  return getOrCreateLtAuthClient({
19
20
  baseURL: useProxy ? "" : authBaseURL,
20
21
  basePath,
@@ -79,6 +79,13 @@ export declare function resetLtAuthClientSingleton(): void;
79
79
  * Get or create the auth client singleton.
80
80
  * This is the main entry point for accessing the auth client.
81
81
  * If plugins were registered after initial creation, the client is recreated.
82
+ *
83
+ * WARNING — on the server this singleton is shared by EVERY concurrent render in
84
+ * the Node process, not scoped to one request. It is safe today only because
85
+ * nothing user-specific hangs on it. Never attach request-scoped data to it —
86
+ * forwarded cookies, an Authorization header, a per-user fetch option: one
87
+ * user's session would be rendered into another user's response. Forwarding the
88
+ * browser's cookies during SSR needs a client created per request, not this one.
82
89
  */
83
90
  export declare function getOrCreateLtAuthClient(config?: LtAuthClientConfig): LtAuthClient;
84
91
  /**
@@ -7,9 +7,22 @@ export async function waitForHydration(page, options = {}) {
7
7
  });
8
8
  }
9
9
  export async function gotoAndWaitForHydration(page, url, options = {}) {
10
- await page.goto(url);
10
+ await gotoWithAbortRetry(page, url);
11
11
  await waitForHydration(page, options);
12
12
  }
13
+ async function gotoWithAbortRetry(page, url, maxAttempts = 3) {
14
+ for (let attempt = 1; ; attempt++) {
15
+ try {
16
+ await page.goto(url);
17
+ return;
18
+ } catch (error) {
19
+ const message = error instanceof Error ? error.message : String(error);
20
+ if (attempt >= maxAttempts || !message.includes("net::ERR_ABORTED")) {
21
+ throw error;
22
+ }
23
+ }
24
+ }
25
+ }
13
26
  export async function waitForURLAndHydration(page, url, options = {}) {
14
27
  const { timeout = 3e4, hydrationTimeout } = options;
15
28
  await page.waitForURL(url, { timeout });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenne.tech/nuxt-extensions",
3
- "version": "1.18.1",
3
+ "version": "1.18.2",
4
4
  "description": "Reusable Nuxt 4 composables, components, and Better-Auth integration for lenne.tech projects",
5
5
  "repository": {
6
6
  "type": "git",
@@ -61,7 +61,7 @@
61
61
  "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxt prepare playground",
62
62
  "build": "nuxt-module-build build",
63
63
  "lint": "oxlint src/ scripts/",
64
- "lint:fix": "oxlint --fix --fix-suggestions src/ scripts/",
64
+ "lint:fix": "oxlint --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",
@@ -102,17 +102,18 @@
102
102
  "@better-auth/passkey": "1.7.1",
103
103
  "@nuxt/module-builder": "1.0.3",
104
104
  "@nuxt/schema": "4.5.2",
105
- "@nuxt/ui": "4.11.0",
106
- "@playwright/test": "1.62.1",
107
- "@types/node": "26.2.0",
105
+ "@nuxt/ui": "4.11.2",
106
+ "@playwright/test": "1.63.0",
107
+ "@types/node": "26.6.3",
108
108
  "@vitest/coverage-v8": "4.1.11",
109
- "@vue/server-renderer": "3.5.41",
109
+ "@vue/server-renderer": "3.5.43",
110
110
  "better-auth": "1.7.1",
111
- "happy-dom": "20.11.6",
111
+ "cross-spawn": "7.0.6",
112
+ "happy-dom": "20.14.5",
112
113
  "nuxt": "4.5.2",
113
- "oxfmt": "0.64.0",
114
- "oxlint": "1.79.0",
115
- "reka-ui": "2.10.3",
114
+ "oxfmt": "0.70.0",
115
+ "oxlint": "1.85.0",
116
+ "reka-ui": "2.10.4",
116
117
  "tus-js-client": "4.3.1",
117
118
  "typescript": "5.9.3",
118
119
  "vitest": "4.1.11",