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,50 +1,226 @@
1
+ import { AuthClient, InMemoryStorage, defaultStorage } from "@convex-dev/auth/browser";
2
+ import { ConvexHttpClient } from "convex/browser";
3
+ import { makeFunctionReference } from "convex/server";
1
4
  import { defineNuxtPlugin, useRuntimeConfig } from "nuxt/app";
5
+ import { readonly, shallowRef, watch } from "vue";
2
6
  import { useConvexAuth } from "./composables/useConvexAuth.js";
3
7
  import {
4
- consumeOAuthCodeFromUrl,
5
- getAuthToken,
6
- hasPendingOAuthCallback,
7
- hydrateAuthFromStorage,
8
- useAuthProviderState
9
- } from "./composables/useAuth.js";
10
- import { setConvexAuthModuleDefaults } from "./utils/authClientOptions.js";
11
- import { tryUseConvexContext } from "./utils/context.js";
8
+ OAUTH_CODE_PARAM,
9
+ OAUTH_ERROR_PARAM,
10
+ convexOAuth
11
+ } from "./auth/oauth.js";
12
+ import { postAuth, retryingTokenFetcher } from "./auth/sessionRoutes.js";
13
+ import { getConvexAuthClientOptions } from "./utils/authClientOptions.js";
14
+ import { useConvexAuthTokenState } from "./utils/authCookie.js";
15
+ import {
16
+ isConvexAuth,
17
+ resolveAuthApiNames,
18
+ resolveAuthMode,
19
+ resolveAuthRoutes
20
+ } from "./utils/authStorage.js";
21
+ import {
22
+ tryUseConvexContext
23
+ } from "./utils/context.js";
24
+ function sessionStorageOrUndefined() {
25
+ try {
26
+ return typeof window !== "undefined" ? window.sessionStorage : void 0;
27
+ } catch {
28
+ return void 0;
29
+ }
30
+ }
12
31
  export default defineNuxtPlugin({
13
32
  name: "convex-nuxt-auth",
14
33
  dependsOn: ["convex-nuxt-client"],
15
- setup() {
34
+ setup(nuxtApp) {
16
35
  const config = useRuntimeConfig();
17
36
  const convexConfig = config.public.convex;
18
- if (!convexConfig?.url) {
37
+ const auth = convexConfig?.auth;
38
+ if (!convexConfig?.url || !isConvexAuth(auth)) {
19
39
  return;
20
40
  }
21
- if (!tryUseConvexContext()) {
41
+ const ctx = tryUseConvexContext();
42
+ const convex = ctx?.client;
43
+ if (!ctx || !convex) {
22
44
  return;
23
45
  }
24
- const auth = convexConfig.auth;
25
- if (auth?.provider === "convex-auth") {
26
- setConvexAuthModuleDefaults({
27
- storageNamespace: auth.storageNamespace,
28
- storage: auth.storage,
29
- shouldHandleCode: auth.shouldHandleCode
46
+ const mode = resolveAuthMode(auth);
47
+ const apiNames = resolveAuthApiNames(auth);
48
+ const baseURL = config.app?.baseURL ?? "/";
49
+ const routes = resolveAuthRoutes(auth);
50
+ const route = (path) => baseURL.replace(/\/+$/, "") + path;
51
+ const options = getConvexAuthClientOptions();
52
+ const tokenState = useConvexAuthTokenState();
53
+ const storage = options.storage ?? (auth?.storage === "inMemory" ? new InMemoryStorage() : defaultStorage());
54
+ const storageNamespace = auth?.storageNamespace ?? ctx.url;
55
+ const replaceUrl = options.replaceUrl ?? ((url) => {
56
+ window.history.replaceState(window.history.state, "", url);
57
+ const router = nuxtApp.$router;
58
+ void router?.isReady().then(() => {
59
+ const current = router.currentRoute.value;
60
+ if (!(OAUTH_CODE_PARAM in current.query) && !(OAUTH_ERROR_PARAM in current.query)) {
61
+ return;
62
+ }
63
+ const query = { ...current.query };
64
+ delete query[OAUTH_CODE_PARAM];
65
+ delete query[OAUTH_ERROR_PARAM];
66
+ void router.replace({ path: current.path, query, hash: current.hash });
30
67
  });
31
- }
32
- const pendingOAuth = hasPendingOAuthCallback();
33
- if (!pendingOAuth) {
34
- hydrateAuthFromStorage();
35
- }
36
- const { isLoading, hasSession } = useAuthProviderState();
37
- useConvexAuth({
38
- fetchToken: ({ forceRefreshToken }) => getAuthToken({ forceRefreshToken }),
39
- isLoading,
40
- isAuthenticated: hasSession
41
68
  });
42
- if (pendingOAuth) {
43
- void consumeOAuthCodeFromUrl().catch(() => false).then((ok) => {
44
- if (!ok) {
45
- hydrateAuthFromStorage();
69
+ const flowStorage = !options.storage && auth?.storage === "inMemory" ? sessionStorageOrUndefined() : void 0;
70
+ const signIns = options.ambientSignIns ?? [
71
+ convexOAuth(flowStorage ? { flowStorage, namespace: storageNamespace } : {})
72
+ ];
73
+ const convexMutationApi = {
74
+ mutation: (fn, args) => convex.mutation(fn, args)
75
+ };
76
+ let authClient;
77
+ let signInApi;
78
+ if (mode === "ssr") {
79
+ const proxy = new ConvexHttpClient(`${route(routes.signIn)}?path=`, {
80
+ skipConvexDeploymentUrlCheck: true
81
+ });
82
+ const withAuth = () => {
83
+ const token = authClient.getAccessToken();
84
+ if (token !== null) {
85
+ proxy.setAuth(token);
86
+ } else {
87
+ proxy.clearAuth();
88
+ }
89
+ return proxy;
90
+ };
91
+ signInApi = {
92
+ mutation: (fn, args) => withAuth().mutation(fn, args),
93
+ action: (fn, args) => withAuth().action(fn, args)
94
+ };
95
+ authClient = new AuthClient({
96
+ mode: "ssr",
97
+ authApi: {
98
+ refreshSession: async () => (await postAuth(route(routes.refresh))).tokens,
99
+ signOut: async () => {
100
+ await postAuth(route(routes.signOut));
101
+ }
102
+ },
103
+ storage,
104
+ storageNamespace,
105
+ // The server refreshed on our behalf, so this is the freshest token.
106
+ initialAccessToken: tokenState.value,
107
+ verbose: auth?.verbose,
108
+ ambientSignIns: {
109
+ signIns,
110
+ signInApi,
111
+ convex: convexMutationApi,
112
+ replaceUrl
46
113
  }
47
114
  });
115
+ } else {
116
+ const http = new ConvexHttpClient(ctx.url);
117
+ const refreshSession = makeFunctionReference(apiNames.refreshSession);
118
+ const signOutRef = makeFunctionReference(apiNames.signOut);
119
+ signInApi = {
120
+ mutation: (fn, args) => convex.mutation(fn, args),
121
+ action: (fn, args) => convex.action(fn, args)
122
+ };
123
+ authClient = new AuthClient({
124
+ mode: "spa",
125
+ authApi: {
126
+ refreshSession: (refreshToken) => http.mutation(refreshSession, { refreshToken }),
127
+ signOut: async (refreshToken) => {
128
+ await http.mutation(signOutRef, { refreshToken });
129
+ }
130
+ },
131
+ storage,
132
+ storageNamespace,
133
+ verbose: auth?.verbose,
134
+ ambientSignIns: {
135
+ signIns,
136
+ signInApi,
137
+ convex: convexMutationApi,
138
+ replaceUrl
139
+ }
140
+ });
141
+ }
142
+ const state = shallowRef(authClient.getSnapshot());
143
+ authClient.subscribe(() => {
144
+ state.value = authClient.getSnapshot();
145
+ });
146
+ const syncTokenState = () => {
147
+ if (!state.value.isLoading) {
148
+ tokenState.value = state.value.token;
149
+ }
150
+ };
151
+ if (nuxtApp.isHydrating) {
152
+ nuxtApp.hooks.hookOnce("app:suspense:resolve", () => {
153
+ syncTokenState();
154
+ watch(state, syncTokenState);
155
+ });
156
+ } else {
157
+ watch(state, syncTokenState, { immediate: true });
48
158
  }
159
+ const ambientCache = /* @__PURE__ */ new Map();
160
+ const ambientValue = (id, key) => {
161
+ const cacheKey = `${id}:${key}`;
162
+ let cached = ambientCache.get(cacheKey);
163
+ if (!cached) {
164
+ const reader = authClient.ambientSignInValues(id);
165
+ const value = shallowRef(reader.get(key));
166
+ reader.subscribe(key, () => {
167
+ value.value = reader.get(key);
168
+ });
169
+ cached = readonly(value);
170
+ ambientCache.set(cacheKey, cached);
171
+ }
172
+ return cached;
173
+ };
174
+ const binding = {
175
+ mode,
176
+ state,
177
+ signInApi,
178
+ setSession: (session) => authClient.setSession(session),
179
+ signOut: () => authClient.signOut(),
180
+ ambientValue
181
+ };
182
+ ctx.convexAuth = binding;
183
+ const convexAuth = useConvexAuth({
184
+ // A refresh that fails (outage, proxy error) is retried with backoff
185
+ // rather than thrown into ConvexClient or treated as signed out.
186
+ fetchToken: retryingTokenFetcher((args) => authClient.fetchAccessToken(args), {
187
+ hasSession: () => authClient.getAccessToken() !== null,
188
+ onRetry: (error, delayMs) => {
189
+ if (import.meta.dev || auth?.verbose) {
190
+ console.warn(`[use-convex] Session refresh failed; retrying in ${delayMs}ms.`, error);
191
+ }
192
+ }
193
+ }),
194
+ isLoading: () => state.value.isLoading,
195
+ isAuthenticated: () => state.value.isAuthenticated
196
+ });
197
+ const isAuthenticatedRef = makeFunctionReference(
198
+ apiNames.isAuthenticated
199
+ );
200
+ let stopWatching = null;
201
+ watch(
202
+ () => convexAuth.isAuthenticated.value,
203
+ (authenticated) => {
204
+ stopWatching?.();
205
+ stopWatching = null;
206
+ if (!authenticated) {
207
+ return;
208
+ }
209
+ const unsubscribe = convex.onUpdate(
210
+ isAuthenticatedRef,
211
+ {},
212
+ (hasLiveSession) => {
213
+ if (hasLiveSession === false) {
214
+ void authClient.signOut();
215
+ }
216
+ },
217
+ () => {
218
+ }
219
+ );
220
+ stopWatching = () => unsubscribe();
221
+ },
222
+ { immediate: true }
223
+ );
224
+ void authClient.init();
49
225
  }
50
226
  });
@@ -1,5 +1,6 @@
1
- import { defineNuxtPlugin, useRuntimeConfig } from "nuxt/app";
2
- import { useSsrTokenRef } from "./utils/authCookie.js";
1
+ import { defineNuxtPlugin, useRequestEvent, useRuntimeConfig } from "nuxt/app";
2
+ import { useConvexAuthTokenState, useSsrTokenRef } from "./utils/authCookie.js";
3
+ import { isSsrConvexAuth } from "./utils/authStorage.js";
3
4
  import { createHttpClient } from "./utils/http.js";
4
5
  import { convexNuxtKey, createAuthContext } from "./utils/context.js";
5
6
  import { warnMissingConvexUrl } from "./utils/errors.js";
@@ -15,6 +16,11 @@ export default defineNuxtPlugin({
15
16
  }
16
17
  return;
17
18
  }
19
+ if (isSsrConvexAuth(convexConfig?.auth)) {
20
+ const event = useRequestEvent();
21
+ const token = event?.context?.convexAuthToken;
22
+ useConvexAuthTokenState().value = token ?? null;
23
+ }
18
24
  const ssrToken = useSsrTokenRef();
19
25
  const auth = createAuthContext();
20
26
  if (ssrToken.value) {
@@ -1,7 +1,12 @@
1
1
  import type { H3Event } from 'h3';
2
2
  /**
3
- * Read the Convex JWT from the configured auth cookie on this request.
4
- * Returns `undefined` when the cookie is missing or auth cookies are disabled.
3
+ * Read the Convex JWT for this request.
4
+ *
5
+ * - Convex Auth (SSR mode): the access token the session middleware
6
+ * refreshed for this request, else the access-token cookie while valid.
7
+ * - BYO providers: the configured `convex.auth.cookie`.
8
+ *
9
+ * Returns `undefined` when there is no session or auth cookies are disabled.
5
10
  */
6
11
  export declare function getConvexToken(event: H3Event): string | undefined;
7
12
  /**
@@ -1,16 +1,27 @@
1
1
  import { createError, getCookie } from "h3";
2
- import { resolveAuthCookieName } from "../utils/authStorage.js";
2
+ import { isJwtExpiring, isSsrConvexAuth, resolveAuthCookieName } from "../utils/authStorage.js";
3
3
  import { resolveFetchToken } from "../utils/fetchToken.js";
4
4
  import { readConvexConfig } from "./convexConfig.js";
5
5
  export function getConvexToken(event) {
6
- const cookieName = resolveAuthCookieName(readConvexConfig(event)?.auth);
6
+ const auth = readConvexConfig(event)?.auth;
7
+ if (isSsrConvexAuth(auth)) {
8
+ const fromMiddleware = event.context.convexAuthToken;
9
+ if (fromMiddleware !== void 0) {
10
+ return fromMiddleware ?? void 0;
11
+ }
12
+ }
13
+ const cookieName = resolveAuthCookieName(auth);
7
14
  if (!cookieName) {
8
15
  return void 0;
9
16
  }
10
- return resolveFetchToken({
17
+ const token = resolveFetchToken({
11
18
  cookieName,
12
19
  cookieValue: getCookie(event, cookieName)
13
20
  });
21
+ if (token && isSsrConvexAuth(auth) && isJwtExpiring(token, 0)) {
22
+ return void 0;
23
+ }
24
+ return token;
14
25
  }
15
26
  export function requireConvexAuth(event) {
16
27
  const token = getConvexToken(event);
@@ -0,0 +1,3 @@
1
+ /** Convex Auth v2 `refreshHandler` from `@convex-dev/auth/ssr`. */
2
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
3
+ export default _default;
@@ -0,0 +1,5 @@
1
+ import { defineEventHandler } from "h3";
2
+ import { runWebHandler, useConvexAuthServer } from "./setup.js";
3
+ export default defineEventHandler(
4
+ (event) => runWebHandler(event, useConvexAuthServer(event).refreshHandler)
5
+ );
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Resolve the Convex Auth access token for this request (SSR mode).
3
+ *
4
+ * Access tokens live ~60s, so most page loads find an expired one: refresh
5
+ * from the httpOnly refresh cookie, rotate both cookies on the response, and
6
+ * leave the fresh token on `event.context.convexAuthToken` for SSR queries,
7
+ * `getConvexToken`, and the Nitro `fetch*` helpers.
8
+ */
9
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
10
+ export default _default;
@@ -0,0 +1,37 @@
1
+ import { defineEventHandler, getCookie, getRequestURL } from "h3";
2
+ import { useRuntimeConfig } from "nitropack/runtime";
3
+ import {
4
+ CONVEX_AUTH_JWT_COOKIE,
5
+ CONVEX_AUTH_REFRESH_COOKIE,
6
+ DEFAULT_AUTH_ROUTE_PREFIX,
7
+ isJwtExpiring
8
+ } from "../../utils/authStorage.js";
9
+ import { createServerAuthSession } from "./setup.js";
10
+ export default defineEventHandler(async (event) => {
11
+ const context = event.context;
12
+ if (context.convexAuthToken !== void 0) {
13
+ return;
14
+ }
15
+ const pathname = getRequestURL(event).pathname;
16
+ const config = useRuntimeConfig(event);
17
+ const baseURL = (config.app?.baseURL ?? "/").replace(/\/+$/, "");
18
+ const auth = config.public?.convex?.auth;
19
+ const prefix = baseURL + (auth?.routePrefix ?? DEFAULT_AUTH_ROUTE_PREFIX).replace(/\/+$/, "");
20
+ if (pathname.startsWith(prefix + "/") || // Build assets and dev tooling never need a session. Other paths with a
21
+ // dot (`/users/jane.doe`, `/api/report.json`) are pages and endpoints
22
+ // that may. Files in `public/` are served by Nitro before middleware.
23
+ pathname.startsWith(`${baseURL}/_nuxt/`) || pathname.startsWith(`${baseURL}/__nuxt_devtools__`) || pathname.startsWith(`${baseURL}/__convex_devtools`) || pathname === `${baseURL}/favicon.ico`) {
24
+ return;
25
+ }
26
+ const jwt = getCookie(event, CONVEX_AUTH_JWT_COOKIE) || null;
27
+ const refresh = getCookie(event, CONVEX_AUTH_REFRESH_COOKIE) || null;
28
+ if (refresh === null) {
29
+ context.convexAuthToken = jwt !== null && !isJwtExpiring(jwt, 0) ? jwt : null;
30
+ return;
31
+ }
32
+ try {
33
+ context.convexAuthToken = await createServerAuthSession(event).getToken();
34
+ } catch {
35
+ context.convexAuthToken = jwt !== null && !isJwtExpiring(jwt, 0) ? jwt : null;
36
+ }
37
+ });
@@ -0,0 +1,21 @@
1
+ import { ServerAuthSession, setupConvexAuthServer, type AuthCookieOptions, type CookieStore } from '@convex-dev/auth/ssr';
2
+ import type { H3Event } from 'h3';
3
+ import { type ConvexAuthServerRuntimeConfig } from '../../utils/authStorage.js';
4
+ export type { ConvexAuthServerRuntimeConfig };
5
+ export declare function resolveCookieOptions(event: H3Event, server: ConvexAuthServerRuntimeConfig): AuthCookieOptions;
6
+ type Handlers = ReturnType<typeof setupConvexAuthServer>;
7
+ /**
8
+ * `setupConvexAuthServer` built from runtime config, cached per
9
+ * deployment + cookie attributes (`secure` differs on localhost).
10
+ */
11
+ export declare function useConvexAuthServer(event: H3Event): Handlers;
12
+ /** Run a WHATWG handler from `@convex-dev/auth/ssr` on an H3 event. */
13
+ export declare function runWebHandler(event: H3Event, handler: (request: Request) => Promise<Response>): Promise<void>;
14
+ /** `CookieStore` over H3 request/response cookies. */
15
+ export declare function h3CookieStore(event: H3Event): CookieStore;
16
+ /**
17
+ * A `ServerAuthSession` for this request: reads the access/refresh cookies,
18
+ * refreshes when the access token is missing or near expiry, and writes the
19
+ * rotated cookies onto the response.
20
+ */
21
+ export declare function createServerAuthSession(event: H3Event): ServerAuthSession;
@@ -0,0 +1,90 @@
1
+ import {
2
+ ServerAuthSession,
3
+ setupConvexAuthServer
4
+ } from "@convex-dev/auth/ssr";
5
+ import { ConvexHttpClient } from "convex/browser";
6
+ import { makeFunctionReference } from "convex/server";
7
+ import {
8
+ createError,
9
+ deleteCookie,
10
+ getCookie,
11
+ getRequestHeader,
12
+ sendWebResponse,
13
+ setCookie,
14
+ toWebRequest
15
+ } from "h3";
16
+ import { useRuntimeConfig } from "nitropack/runtime";
17
+ import { MISSING_URL_HINT } from "../../utils/errors.js";
18
+ import {
19
+ resolveAuthApiNames
20
+ } from "../../utils/authStorage.js";
21
+ function resolveConfig(event) {
22
+ const config = useRuntimeConfig(event);
23
+ const pub = config.public?.convex;
24
+ const convexUrl = pub?.url ?? process.env.NUXT_PUBLIC_CONVEX_URL;
25
+ if (!convexUrl) {
26
+ throw createError({ statusCode: 500, message: MISSING_URL_HINT });
27
+ }
28
+ return {
29
+ convexUrl,
30
+ auth: pub?.auth,
31
+ server: config.convexAuth ?? {}
32
+ };
33
+ }
34
+ function isLocalHost(event) {
35
+ const host = getRequestHeader(event, "host") ?? "";
36
+ return host.startsWith("localhost") || host.startsWith("127.0.0.1") || host.startsWith("[::1]");
37
+ }
38
+ export function resolveCookieOptions(event, server) {
39
+ return {
40
+ secure: server.cookie?.secure ?? !isLocalHost(event),
41
+ ...server.cookie?.domain ? { domain: server.cookie.domain } : {},
42
+ ...server.cookie?.path ? { path: server.cookie.path } : {}
43
+ };
44
+ }
45
+ const cache = /* @__PURE__ */ new Map();
46
+ export function useConvexAuthServer(event) {
47
+ const { convexUrl, auth, server } = resolveConfig(event);
48
+ const cookieOptions = resolveCookieOptions(event, server);
49
+ const api = resolveAuthApiNames(auth);
50
+ const key = JSON.stringify([convexUrl, api, server, cookieOptions]);
51
+ let handlers = cache.get(key);
52
+ if (!handlers) {
53
+ handlers = setupConvexAuthServer({
54
+ convexUrl,
55
+ refreshSession: makeFunctionReference(api.refreshSession),
56
+ signOut: makeFunctionReference(api.signOut),
57
+ signIn: (server.signIn ?? []).map((name) => makeFunctionReference(name)),
58
+ cookieOptions,
59
+ ...server.allowedOrigins?.length ? { allowedOrigins: server.allowedOrigins } : {}
60
+ });
61
+ cache.set(key, handlers);
62
+ }
63
+ return handlers;
64
+ }
65
+ export async function runWebHandler(event, handler) {
66
+ const response = await handler(toWebRequest(event));
67
+ return sendWebResponse(event, response);
68
+ }
69
+ export function h3CookieStore(event) {
70
+ return {
71
+ get: (name) => getCookie(event, name) || void 0,
72
+ set: (name, value, options) => {
73
+ setCookie(event, name, value, options);
74
+ },
75
+ delete: (name, options) => {
76
+ deleteCookie(event, name, options);
77
+ }
78
+ };
79
+ }
80
+ export function createServerAuthSession(event) {
81
+ const { convexUrl, auth, server } = resolveConfig(event);
82
+ const api = resolveAuthApiNames(auth);
83
+ const http = new ConvexHttpClient(convexUrl);
84
+ const refreshSession = makeFunctionReference(api.refreshSession);
85
+ return new ServerAuthSession({
86
+ refreshSession: (refreshToken) => http.mutation(refreshSession, { refreshToken }),
87
+ cookies: h3CookieStore(event),
88
+ cookieOptions: resolveCookieOptions(event, server)
89
+ });
90
+ }
@@ -0,0 +1,3 @@
1
+ /** Convex Auth v2 `convexProxyHandler` from `@convex-dev/auth/ssr`. */
2
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
3
+ export default _default;
@@ -0,0 +1,5 @@
1
+ import { defineEventHandler } from "h3";
2
+ import { runWebHandler, useConvexAuthServer } from "./setup.js";
3
+ export default defineEventHandler(
4
+ (event) => runWebHandler(event, useConvexAuthServer(event).convexProxyHandler)
5
+ );
@@ -0,0 +1,3 @@
1
+ /** Convex Auth v2 `signOutHandler` from `@convex-dev/auth/ssr`. */
2
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
3
+ export default _default;
@@ -0,0 +1,5 @@
1
+ import { defineEventHandler } from "h3";
2
+ import { runWebHandler, useConvexAuthServer } from "./setup.js";
3
+ export default defineEventHandler(
4
+ (event) => runWebHandler(event, useConvexAuthServer(event).signOutHandler)
5
+ );
@@ -1,12 +1,8 @@
1
1
  import type { H3Event } from 'h3';
2
+ import type { ConvexAuthConfig } from '../utils/authStorage.js';
2
3
  export interface ConvexPublicConfig {
3
4
  url?: string;
4
- auth?: {
5
- provider?: string;
6
- cookie?: string;
7
- httpOnly?: boolean;
8
- presentCookie?: string;
9
- };
5
+ auth?: ConvexAuthConfig;
10
6
  }
11
7
  /** Read `runtimeConfig.public.convex`, or `undefined` outside a Nitro request. */
12
8
  export declare function readConvexConfig(event?: H3Event): ConvexPublicConfig | undefined;
@@ -8,7 +8,8 @@ export interface ConvexFetchOptions {
8
8
  url?: string;
9
9
  /**
10
10
  * JWT for this call. Prefer per-request tokens — never put JWTs in public config.
11
- * When omitted and `event` is passed, falls back to `convex.auth.cookie` if set.
11
+ * When omitted and `event` is passed, falls back to the request's session
12
+ * (Convex Auth SSR mode) or `convex.auth.cookie` (BYO).
12
13
  * Ignored when {@link adminToken} is set (admin auth clears user JWT).
13
14
  */
14
15
  token?: string;
@@ -1,6 +1,5 @@
1
- import { getCookie } from "h3";
2
1
  import { createHttpClient } from "../utils/http.js";
3
- import { resolveAuthCookieName } from "../utils/authStorage.js";
2
+ import { getConvexToken } from "./auth.js";
4
3
  import { resolveFetchToken } from "../utils/fetchToken.js";
5
4
  import { missingConvexUrlError } from "../utils/errors.js";
6
5
  import { readConvexConfig } from "./convexConfig.js";
@@ -22,14 +21,10 @@ export function resolveToken(options) {
22
21
  if (options.token !== void 0) {
23
22
  return resolveFetchToken({ token: options.token });
24
23
  }
25
- const cookieName = resolveAuthCookieName(readConvexConfig(options.event)?.auth);
26
- if (!cookieName || !options.event) {
24
+ if (!options.event) {
27
25
  return void 0;
28
26
  }
29
- return resolveFetchToken({
30
- cookieName,
31
- cookieValue: getCookie(options.event, cookieName)
32
- });
27
+ return getConvexToken(options.event);
33
28
  }
34
29
  function setupClient(options = {}) {
35
30
  const token = options.adminToken ? void 0 : resolveToken(options);