use-convex 1.3.0 → 2.0.0

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.
Files changed (51) hide show
  1. package/README.md +104 -59
  2. package/dist/module.d.mts +62 -39
  3. package/dist/module.mjs +68 -17
  4. package/dist/runtime/auth/oauth.d.ts +96 -0
  5. package/dist/runtime/auth/oauth.js +170 -0
  6. package/dist/runtime/auth/sessionRoutes.d.ts +37 -0
  7. package/dist/runtime/auth/sessionRoutes.js +41 -0
  8. package/dist/runtime/composables/useAuth.d.ts +81 -48
  9. package/dist/runtime/composables/useAuth.js +69 -461
  10. package/dist/runtime/composables/useAuthToken.d.ts +2 -2
  11. package/dist/runtime/composables/useAuthToken.js +4 -0
  12. package/dist/runtime/composables/useConvexAuth.js +1 -1
  13. package/dist/runtime/composables/useConvexPaginatedQuery.js +6 -1
  14. package/dist/runtime/composables/useConvexQuery.js +6 -1
  15. package/dist/runtime/plugin.auth.client.d.ts +8 -3
  16. package/dist/runtime/plugin.auth.client.js +207 -31
  17. package/dist/runtime/plugin.server.js +8 -2
  18. package/dist/runtime/server/auth.d.ts +7 -2
  19. package/dist/runtime/server/auth.js +14 -3
  20. package/dist/runtime/server/convexAuth/refresh.d.ts +3 -0
  21. package/dist/runtime/server/convexAuth/refresh.js +5 -0
  22. package/dist/runtime/server/convexAuth/session.middleware.d.ts +10 -0
  23. package/dist/runtime/server/convexAuth/session.middleware.js +37 -0
  24. package/dist/runtime/server/convexAuth/setup.d.ts +21 -0
  25. package/dist/runtime/server/convexAuth/setup.js +90 -0
  26. package/dist/runtime/server/convexAuth/signin.d.ts +3 -0
  27. package/dist/runtime/server/convexAuth/signin.js +5 -0
  28. package/dist/runtime/server/convexAuth/signout.d.ts +3 -0
  29. package/dist/runtime/server/convexAuth/signout.js +5 -0
  30. package/dist/runtime/server/convexConfig.d.ts +2 -6
  31. package/dist/runtime/server/fetch.d.ts +2 -1
  32. package/dist/runtime/server/fetch.js +3 -8
  33. package/dist/runtime/utils/authClientOptions.d.ts +33 -40
  34. package/dist/runtime/utils/authClientOptions.js +1 -64
  35. package/dist/runtime/utils/authCookie.d.ts +8 -14
  36. package/dist/runtime/utils/authCookie.js +23 -27
  37. package/dist/runtime/utils/authStorage.d.ts +76 -79
  38. package/dist/runtime/utils/authStorage.js +60 -141
  39. package/dist/runtime/utils/context.d.ts +40 -3
  40. package/dist/types.d.mts +4 -2
  41. package/package.json +10 -5
  42. package/dist/runtime/server/api/convex/auth/session.d.ts +0 -36
  43. package/dist/runtime/server/api/convex/auth/session.js +0 -90
  44. package/dist/runtime/server/authCookies.d.ts +0 -9
  45. package/dist/runtime/server/authCookies.js +0 -64
  46. package/dist/runtime/server/sameOrigin.d.ts +0 -14
  47. package/dist/runtime/server/sameOrigin.js +0 -29
  48. package/dist/runtime/utils/authMutex.d.ts +0 -15
  49. package/dist/runtime/utils/authMutex.js +0 -47
  50. package/dist/runtime/utils/oauthRedirect.d.ts +0 -5
  51. package/dist/runtime/utils/oauthRedirect.js +0 -13
@@ -1,476 +1,84 @@
1
- import { ConvexHttpClient } from "convex/browser";
2
- import { makeFunctionReference } from "convex/server";
3
- import { computed, nextTick } from "vue";
4
- import { useRuntimeConfig, useState } from "nuxt/app";
1
+ import { computed, ref, shallowRef } from "vue";
2
+ import { useConvexContext } from "../utils/context.js";
5
3
  import { useConvexAuth } from "./useConvexAuth.js";
6
- import { missingConvexUrlError, unreachableConvexUrlError } from "../utils/errors.js";
7
- import { withRefreshMutex } from "../utils/authMutex.js";
8
- import { useAuthJwtCookie, useAuthPresentCookie } from "../utils/authCookie.js";
9
- import { getConvexAuthClientOptions, setConvexAuthModuleDefaults } from "../utils/authClientOptions.js";
10
4
  import {
11
- flattenSignInParams,
12
- isHttpOnlyAuth,
13
- JWT_STORAGE_KEY,
14
- readLocalAsync,
15
- readStored,
16
- readVerifier,
17
- readVerifierAsync,
18
- REFRESH_TOKEN_STORAGE_KEY,
19
- shouldConsumeOAuthCode,
20
- storageKey,
21
- VERIFIER_STORAGE_KEY,
22
- writeLocalAsync,
23
- writeVerifier
24
- } from "../utils/authStorage.js";
25
- import { tryUseConvexContext } from "../utils/context.js";
26
- import { parseOAuthRedirect } from "../utils/oauthRedirect.js";
27
- const authSignIn = makeFunctionReference("auth:signIn");
28
- const authSignOut = makeFunctionReference("auth:signOut");
29
- const RETRY_BACKOFF = [500, 2e3];
30
- const RETRY_JITTER = 100;
5
+ OAUTH_ACTIONS_KEY,
6
+ OAUTH_FLOW_ERROR_KEY,
7
+ OAUTH_SETUP_ID
8
+ } from "../auth/oauth.js";
9
+ function useBinding(name) {
10
+ const ctx = useConvexContext();
11
+ if (!import.meta.server && !ctx.convexAuth) {
12
+ throw new Error(
13
+ `[use-convex] ${name} requires \`convex.auth.provider: 'convex-auth'\` in nuxt.config.`
14
+ );
15
+ }
16
+ return ctx.convexAuth ?? null;
17
+ }
18
+ function requireBinding(name) {
19
+ const binding = useConvexContext().convexAuth;
20
+ if (!binding) {
21
+ throw new Error(`[use-convex] ${name} is browser-only and requires Convex Auth.`);
22
+ }
23
+ return binding;
24
+ }
31
25
  export function useAuth() {
32
- const session = useAuthSession();
33
- if (!tryUseConvexContext()) {
34
- return {
35
- isLoading: computed(() => session.isLoading.value),
36
- isAuthenticated: computed(() => false),
37
- isRefreshing: computed(() => false),
38
- hasSsrSession: computed(() => false),
39
- showAuthedUi: computed(() => false),
40
- error: session.error,
41
- pending: session.pending,
42
- signIn,
43
- signOut
44
- };
45
- }
46
- const convexAuth = useConvexAuth();
26
+ const binding = useBinding("useAuth");
27
+ const auth = useConvexAuth();
47
28
  return {
48
- isLoading: convexAuth.isLoading,
49
- isAuthenticated: convexAuth.isAuthenticated,
50
- isRefreshing: convexAuth.isRefreshing,
51
- hasSsrSession: convexAuth.hasSsrSession,
52
- showAuthedUi: convexAuth.showAuthedUi,
53
- error: session.error,
54
- pending: session.pending,
55
- signIn,
56
- signOut
29
+ ...auth,
30
+ token: computed(() => binding?.state.value.token ?? null),
31
+ setSession: (session) => requireBinding("setSession").setSession(session),
32
+ signOut: () => signOut()
57
33
  };
58
34
  }
59
- export async function signIn(provider, params) {
60
- const session = useAuthSession();
61
- const convexUrl = session.convexUrl;
62
- if (!convexUrl) {
63
- throw missingConvexUrlError("signIn");
64
- }
65
- session.pending.value = true;
66
- session.error.value = null;
67
- try {
68
- const flatParams = flattenSignInParams(params);
69
- const existingVerifier = await readVerifierAsync(session.verifierKey.value) ?? void 0;
70
- await writeVerifier(session.verifierKey.value, null);
71
- const result = await callSignIn(convexUrl, {
72
- provider,
73
- params: flatParams,
74
- verifier: existingVerifier
75
- });
76
- if (result.redirect !== void 0) {
77
- const url = parseOAuthRedirect(result.redirect);
78
- if (result.verifier) {
79
- await writeVerifier(session.verifierKey.value, result.verifier);
80
- }
81
- if (inBrowser()) {
82
- window.location.href = url.toString();
83
- }
84
- return { signingIn: false, redirect: url };
85
- }
86
- if (result.tokens !== void 0) {
87
- await persistTokens(session, result.tokens);
88
- return { signingIn: result.tokens !== null };
89
- }
90
- return { signingIn: false };
91
- } catch (cause) {
92
- const message = isNetworkError(cause) && convexUrl ? unreachableConvexUrlError(convexUrl).message : cause instanceof Error ? cause.message : "Authentication failed";
93
- session.error.value = message;
94
- throw cause;
95
- } finally {
96
- session.pending.value = false;
97
- }
98
- }
99
35
  export async function signOut() {
100
- const session = useAuthSession();
101
- const convexUrl = session.convexUrl;
102
- session.pending.value = true;
103
- session.error.value = null;
104
- try {
105
- if (convexUrl) {
106
- const token = await readLocalAsync(session.jwtKey.value);
107
- const http = new ConvexHttpClient(convexUrl);
108
- if (token) {
109
- http.setAuth(token);
110
- }
111
- try {
112
- await http.action(authSignOut, {});
113
- } catch {
114
- }
115
- }
116
- await persistTokens(session, null);
117
- } finally {
118
- session.pending.value = false;
119
- }
120
- }
121
- export function hydrateAuthFromStorage() {
122
- const session = useAuthSession();
123
- if (!session.convexUrl) {
124
- session.isLoading.value = false;
125
- session.hasSession.value = false;
126
- return;
127
- }
128
- if (session.httpOnly) {
129
- const present = useAuthPresentCookie();
130
- if (present?.value === "1") {
131
- session.hasSession.value = true;
132
- session.isLoading.value = false;
133
- return;
134
- }
135
- session.isLoading.value = true;
136
- void fetchAuthSession().then((result) => {
137
- session.hasSession.value = result.hasSession;
138
- session.isLoading.value = false;
139
- if (result.hasSession) {
140
- const marker = useAuthPresentCookie();
141
- if (marker) {
142
- marker.value = "1";
143
- }
144
- }
145
- });
146
- return;
147
- }
148
- const stored = readStored(session.jwtKey.value);
149
- const applyToken = (token) => {
150
- session.hasSession.value = token !== null;
151
- session.isLoading.value = false;
152
- if (token) {
153
- setJwtCookie(token);
154
- }
155
- };
156
- if (stored instanceof Promise) {
157
- session.isLoading.value = true;
158
- void stored.then(applyToken).catch(() => {
159
- session.hasSession.value = false;
160
- session.isLoading.value = false;
161
- });
162
- return;
163
- }
164
- applyToken(stored);
165
- }
166
- export async function getAuthToken({
167
- forceRefreshToken
168
- }) {
169
- const session = useAuthSession();
170
- const convexUrl = session.convexUrl;
171
- if (!convexUrl) {
172
- return null;
173
- }
174
- if (session.httpOnly) {
175
- return withRefreshMutex(session.refreshKey.value, async () => {
176
- if (!forceRefreshToken) {
177
- const current = await fetchAuthSessionToken();
178
- if (current.token) {
179
- session.hasSession.value = true;
180
- return current.token;
181
- }
182
- }
183
- const refreshed = await refreshAuthSession();
184
- if (!refreshed) {
185
- await clearAuthSession();
186
- session.hasSession.value = false;
187
- return null;
188
- }
189
- session.hasSession.value = true;
190
- return refreshed;
191
- });
192
- }
193
- if (!forceRefreshToken) {
194
- return await readLocalAsync(session.jwtKey.value);
195
- }
196
- return withRefreshMutex(session.refreshKey.value, async () => {
197
- const refreshToken = await readLocalAsync(session.refreshKey.value);
198
- if (!refreshToken) {
199
- await persistTokens(session, null);
200
- return null;
36
+ await requireBinding("signOut").signOut();
37
+ }
38
+ export function useConvexSignIn(fn, options = {}) {
39
+ useBinding("useConvexSignIn");
40
+ const ctx = useConvexContext();
41
+ const pending = ref(false);
42
+ const run = async (args) => {
43
+ const binding = ctx.convexAuth;
44
+ if (!binding) {
45
+ throw new Error("[use-convex] useConvexSignIn().run is browser-only.");
201
46
  }
47
+ pending.value = true;
202
48
  try {
203
- const result = await callSignInWithRetry(convexUrl, { refreshToken });
204
- const tokens = result.tokens ?? null;
205
- if (!tokens) {
206
- await persistTokens(session, null);
207
- return null;
49
+ const call = options.kind === "action" ? binding.signInApi.action : binding.signInApi.mutation;
50
+ const result = await call(fn, args);
51
+ if (result?.status === "complete" && result.tokens) {
52
+ await binding.setSession(result.tokens);
208
53
  }
209
- await persistTokens(session, tokens);
210
- return tokens.token;
211
- } catch {
212
- await persistTokens(session, null);
213
- return null;
214
- }
215
- });
216
- }
217
- function inBrowser() {
218
- if (import.meta.client) {
219
- return true;
220
- }
221
- return import.meta.client !== false && typeof window !== "undefined";
222
- }
223
- export function hasPendingOAuthCallback() {
224
- if (!inBrowser()) {
225
- return false;
226
- }
227
- const session = useAuthSession();
228
- if (!session.convexUrl) {
229
- return false;
230
- }
231
- const code = new URLSearchParams(window.location.search).get("code");
232
- if (!code) {
233
- return false;
234
- }
235
- const gate = getConvexAuthClientOptions().shouldHandleCode;
236
- if (gate === false || typeof gate === "function" && !gate()) {
237
- return false;
238
- }
239
- const verifier = readVerifier(session.verifierKey.value);
240
- if (verifier instanceof Promise) {
241
- return true;
242
- }
243
- return shouldConsumeOAuthCode({
244
- code,
245
- verifier,
246
- shouldHandleCode: gate
247
- });
248
- }
249
- export async function consumeOAuthCodeFromUrl() {
250
- if (!inBrowser()) {
251
- return false;
252
- }
253
- const session = useAuthSession();
254
- if (!session.convexUrl) {
255
- return false;
256
- }
257
- const code = new URLSearchParams(window.location.search).get("code");
258
- const verifier = await readVerifierAsync(session.verifierKey.value);
259
- const gate = getConvexAuthClientOptions().shouldHandleCode;
260
- if (!shouldConsumeOAuthCode({
261
- code,
262
- verifier,
263
- shouldHandleCode: gate
264
- })) {
265
- return false;
266
- }
267
- const url = new URL(window.location.href);
268
- url.searchParams.delete("code");
269
- const relativeUrl = url.pathname + url.search + url.hash;
270
- const replaceURL = getConvexAuthClientOptions().replaceURL;
271
- try {
272
- if (replaceURL) {
273
- await replaceURL(relativeUrl);
274
- } else {
275
- window.history.replaceState({}, "", relativeUrl);
54
+ return result;
55
+ } catch (cause) {
56
+ return { status: "error", userError: { error: "OTHER_ERROR", cause } };
57
+ } finally {
58
+ pending.value = false;
276
59
  }
277
- } catch (cause) {
278
- session.error.value = cause instanceof Error ? cause.message : "OAuth callback failed";
279
- session.isLoading.value = false;
280
- session.pending.value = false;
281
- return false;
282
- }
283
- session.pending.value = true;
284
- session.error.value = null;
285
- session.isLoading.value = true;
286
- try {
287
- await writeVerifier(session.verifierKey.value, null);
288
- const result = await callSignInWithRetry(session.convexUrl, {
289
- params: { code },
290
- verifier
291
- });
292
- await persistTokens(session, result.tokens ?? null);
293
- return result.tokens != null;
294
- } catch (cause) {
295
- const message = cause instanceof Error ? cause.message : "OAuth callback failed";
296
- session.error.value = message;
297
- await persistTokens(session, null);
298
- return false;
299
- } finally {
300
- session.pending.value = false;
301
- }
302
- }
303
- export function useAuthProviderState() {
304
- const session = useAuthSession();
305
- return {
306
- isLoading: computed(() => session.isLoading.value),
307
- hasSession: computed(() => session.hasSession.value)
308
- };
309
- }
310
- function useAuthSession() {
311
- const config = useRuntimeConfig();
312
- const convexConfig = config.public.convex;
313
- const convexUrl = convexConfig?.url;
314
- const authConfig = convexConfig?.auth;
315
- const httpOnly = isHttpOnlyAuth(authConfig);
316
- if (authConfig?.provider === "convex-auth") {
317
- setConvexAuthModuleDefaults({
318
- storageNamespace: authConfig.storageNamespace,
319
- storage: authConfig.storage,
320
- shouldHandleCode: authConfig.shouldHandleCode
321
- });
322
- }
323
- const isLoading = useState("convex-auth-loading", () => true);
324
- const hasSession = useState("convex-auth-has-session", () => false);
325
- const error = useState("convex-auth-error", () => null);
326
- const pending = useState("convex-auth-pending", () => false);
327
- const namespace = getConvexAuthClientOptions().storageNamespace ?? authConfig?.storageNamespace ?? convexUrl;
328
- const jwtKey = computed(
329
- () => namespace ? storageKey(JWT_STORAGE_KEY, namespace) : JWT_STORAGE_KEY
330
- );
331
- const refreshKey = computed(
332
- () => namespace ? storageKey(REFRESH_TOKEN_STORAGE_KEY, namespace) : REFRESH_TOKEN_STORAGE_KEY
333
- );
334
- const verifierKey = computed(
335
- () => namespace ? storageKey(VERIFIER_STORAGE_KEY, namespace) : VERIFIER_STORAGE_KEY
336
- );
337
- return {
338
- convexUrl,
339
- httpOnly,
340
- jwtKey,
341
- refreshKey,
342
- verifierKey,
343
- isLoading,
344
- hasSession,
345
- error,
346
- pending
347
60
  };
348
- }
349
- function setJwtCookie(token) {
350
- const cookie = useAuthJwtCookie();
351
- if (!cookie) {
352
- return;
353
- }
354
- cookie.value = token;
355
- }
356
- function setPresentCookie(value) {
357
- const cookie = useAuthPresentCookie();
358
- if (!cookie) {
359
- return;
360
- }
361
- cookie.value = value;
362
- }
363
- const AUTH_SESSION_PATH = "/api/convex/auth/session";
364
- async function fetchAuthSession() {
365
- try {
366
- return await $fetch(AUTH_SESSION_PATH, {
367
- method: "GET"
368
- });
369
- } catch {
370
- return { hasSession: false };
371
- }
372
- }
373
- async function fetchAuthSessionToken() {
374
- try {
375
- return await $fetch(AUTH_SESSION_PATH, {
376
- method: "POST",
377
- body: { getToken: true }
378
- });
379
- } catch {
380
- return { hasSession: false, token: null };
381
- }
382
- }
383
- async function refreshAuthSession() {
384
- try {
385
- const result = await $fetch(AUTH_SESSION_PATH, {
386
- method: "POST",
387
- body: { refresh: true }
388
- });
389
- return result.token;
390
- } catch {
391
- return null;
392
- }
393
- }
394
- async function clearAuthSession() {
395
- try {
396
- await $fetch(AUTH_SESSION_PATH, { method: "DELETE" });
397
- } catch {
398
- }
399
- setPresentCookie(null);
400
- }
401
- async function writeHttpOnlySession(tokens) {
402
- if (tokens === null) {
403
- await clearAuthSession();
404
- return;
405
- }
406
- await $fetch(AUTH_SESSION_PATH, {
407
- method: "POST",
408
- body: {
409
- token: tokens.token,
410
- refreshToken: tokens.refreshToken
61
+ return { run, pending };
62
+ }
63
+ export function useOAuth() {
64
+ const binding = useBinding("useOAuth");
65
+ if (!binding) {
66
+ return { flowError: shallowRef(null) };
67
+ }
68
+ const value = binding.ambientValue(OAUTH_SETUP_ID, OAUTH_FLOW_ERROR_KEY);
69
+ return { flowError: computed(() => value.value ?? null) };
70
+ }
71
+ export function useOAuthSignIn(refs) {
72
+ const binding = useBinding("useOAuthSignIn");
73
+ const actions = binding?.ambientValue(OAUTH_SETUP_ID, OAUTH_ACTIONS_KEY);
74
+ const signIn = (async (options) => {
75
+ const current = actions?.value;
76
+ if (!current) {
77
+ throw new Error(
78
+ "[use-convex] OAuth is not registered. Include convexOAuth() in configureConvexAuth({ ambientSignIns })."
79
+ );
411
80
  }
81
+ return await current.signIn(refs, options);
412
82
  });
413
- setPresentCookie("1");
414
- }
415
- async function persistTokens(session, tokens) {
416
- if (session.httpOnly) {
417
- if (tokens === null) {
418
- await writeHttpOnlySession(null);
419
- await writeLocalAsync(session.jwtKey.value, null);
420
- await writeLocalAsync(session.refreshKey.value, null);
421
- session.hasSession.value = false;
422
- session.isLoading.value = false;
423
- return;
424
- }
425
- session.hasSession.value = true;
426
- session.isLoading.value = false;
427
- await writeHttpOnlySession(tokens);
428
- return;
429
- }
430
- if (tokens === null) {
431
- await writeLocalAsync(session.jwtKey.value, null);
432
- await writeLocalAsync(session.refreshKey.value, null);
433
- setJwtCookie(null);
434
- session.hasSession.value = false;
435
- session.isLoading.value = false;
436
- return;
437
- }
438
- await writeLocalAsync(session.jwtKey.value, tokens.token);
439
- await writeLocalAsync(session.refreshKey.value, tokens.refreshToken);
440
- session.hasSession.value = true;
441
- session.isLoading.value = false;
442
- nextTick(() => {
443
- setJwtCookie(tokens.token);
444
- });
445
- }
446
- async function callSignIn(convexUrl, args) {
447
- const http = new ConvexHttpClient(convexUrl);
448
- return await http.action(authSignIn, args);
449
- }
450
- async function callSignInWithRetry(convexUrl, args) {
451
- let lastError;
452
- let retry = 0;
453
- while (retry < RETRY_BACKOFF.length) {
454
- try {
455
- return await callSignIn(convexUrl, args);
456
- } catch (e) {
457
- lastError = e;
458
- if (!isNetworkError(e)) {
459
- break;
460
- }
461
- const wait = RETRY_BACKOFF[retry] + RETRY_JITTER * Math.random();
462
- retry++;
463
- await new Promise((resolve) => setTimeout(resolve, wait));
464
- }
465
- }
466
- throw lastError;
467
- }
468
- function isNetworkError(error) {
469
- if (error instanceof TypeError) {
470
- return true;
471
- }
472
- if (error instanceof Error && /network|fetch|Failed to fetch/i.test(error.message)) {
473
- return true;
474
- }
475
- return false;
83
+ return { signIn };
476
84
  }
@@ -4,8 +4,8 @@ import { type ComputedRef } from 'vue';
4
4
  * Current JWT for authenticated HTTP calls (React `@convex-dev/auth`
5
5
  * `useAuthToken` parity).
6
6
  *
7
- * Prefers `ConvexClient.getAuth()`, then the configured `fetchToken`
8
- * (Convex Auth / BYO). Returns `null` when signed out or unavailable.
7
+ * Uses the Convex Auth client token when Convex Auth is enabled; otherwise
8
+ * `ConvexClient.getAuth()`, then the configured BYO `fetchToken`. Returns `null` when signed out or unavailable.
9
9
  */
10
10
  export declare function useAuthToken(): ComputedRef<string | null>;
11
11
  /**
@@ -9,6 +9,10 @@ export function useAuthToken() {
9
9
  return computed(() => null);
10
10
  }
11
11
  const auth = useConvexAuth();
12
+ const binding = ctx.convexAuth;
13
+ if (binding) {
14
+ return computed(() => binding.state.value.token);
15
+ }
12
16
  const refresh = async () => {
13
17
  if (!ctx.client) {
14
18
  token.value = null;
@@ -61,7 +61,7 @@ export function useConvexAuth(setup) {
61
61
  );
62
62
  };
63
63
  watch(
64
- () => [toValue(setup.isLoading) ?? false, toValue(setup.isAuthenticated) ?? true],
64
+ [() => toValue(setup.isLoading) ?? false, () => toValue(setup.isAuthenticated) ?? true],
65
65
  syncFromProvider,
66
66
  { immediate: true }
67
67
  );
@@ -1,3 +1,4 @@
1
+ import { sessionKeyFromToken } from "../utils/authStorage.js";
1
2
  import { convexToJson, jsonToConvex } from "convex/values";
2
3
  import { useAsyncData, useRuntimeConfig } from "nuxt/app";
3
4
  import {
@@ -60,7 +61,11 @@ export async function useConvexPaginatedQuery(query, args = {}, options) {
60
61
  server,
61
62
  watch: [
62
63
  () => toValue(args),
63
- () => options.token ?? ctx.ssrToken.value,
64
+ // Session identity (JWT iss + sub), not the raw token: Convex Auth
65
+ // rotates the access token every minute without changing session,
66
+ // but switching accounts must re-run the snapshot (`live: false`
67
+ // and BYO cookies included).
68
+ () => sessionKeyFromToken(options.token ?? ctx.ssrToken.value),
64
69
  () => requireAuth && ctx.auth.isAuthenticated.value && !!(options.token ?? ctx.ssrToken.value)
65
70
  ]
66
71
  }
@@ -1,3 +1,4 @@
1
+ import { sessionKeyFromToken } from "../utils/authStorage.js";
1
2
  import { convexToJson, jsonToConvex } from "convex/values";
2
3
  import { useAsyncData, useRuntimeConfig } from "nuxt/app";
3
4
  import {
@@ -47,7 +48,11 @@ export async function useConvexQuery(query, args = {}, options = {}) {
47
48
  () => toValue(args),
48
49
  // Re-run HttpClient snapshot when the SSR JWT cookie / token changes
49
50
  // (e.g. after sign-in with live:false, or Refresh).
50
- () => options.token ?? ctx.ssrToken.value,
51
+ // Session identity (JWT iss + sub), not the raw token: Convex Auth
52
+ // rotates the access token every minute without changing session,
53
+ // but switching accounts must re-run the snapshot (`live: false`
54
+ // and BYO cookies included).
55
+ () => sessionKeyFromToken(options.token ?? ctx.ssrToken.value),
51
56
  // Re-run when auth confirms *and* a JWT is available for HttpClient
52
57
  // (readable cookie / SSR). Avoids anonymous client refetches with HttpOnly.
53
58
  () => requireAuth && ctx.auth.isAuthenticated.value && !!(options.token ?? ctx.ssrToken.value)
@@ -1,8 +1,13 @@
1
1
  /**
2
- * First-party Convex Auth wiring (opt-in via `convex.auth.provider: 'convex-auth'`).
2
+ * First-party Convex Auth v2 wiring (`convex.auth.provider: 'convex-auth'`).
3
3
  *
4
- * Must stay synchronous through `useConvexAuth` / `inject` — awaiting first
5
- * drops Vue setup context and caused the "plugin did not start" 500.
4
+ * Builds an `AuthClient` from `@convex-dev/auth/browser` in SSR mode (refresh
5
+ * token in an httpOnly cookie, sign-ins through the Nitro auth proxy) or SPA
6
+ * mode (tokens in browser storage, sign-ins straight to the deployment),
7
+ * then hands its token to `useConvexAuth` and watches `isAuthenticated` so a
8
+ * session revoked server-side signs the client out.
9
+ *
10
+ * Setup stays synchronous so `useConvexAuth` keeps the Nuxt app context.
6
11
  */
7
12
  declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
8
13
  export default _default;