nuxt-convex-module 0.0.1 → 0.9.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.
Files changed (73) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +40 -200
  3. package/dist/chunks/index.mjs +1 -1
  4. package/dist/devtools-client/200.html +1 -1
  5. package/dist/devtools-client/404.html +1 -1
  6. package/dist/devtools-client/_nuxt/{CgIEvOQU.js → 71bSMC-_.js} +1 -1
  7. package/dist/devtools-client/_nuxt/{C2KGYsR4.js → BhmjAr2Q.js} +1 -1
  8. package/dist/devtools-client/_nuxt/{D2ksFYuU.js → C6YdTgGl.js} +2 -2
  9. package/dist/devtools-client/_nuxt/{CtxksWnu.js → _Lf3mfPR.js} +1 -1
  10. package/dist/devtools-client/_nuxt/builds/latest.json +1 -1
  11. package/dist/devtools-client/_nuxt/builds/meta/f9d540d6-1746-4214-8384-31e7759da89f.json +1 -0
  12. package/dist/devtools-client/_nuxt/error-404.CLlwiMp-.css +1 -0
  13. package/dist/devtools-client/_nuxt/error-500.Bxr6fpDU.css +1 -0
  14. package/dist/devtools-client/_nuxt/queries.DNBUjWk2.css +1 -0
  15. package/dist/devtools-client/auth/index.html +1 -1
  16. package/dist/devtools-client/index.html +1 -1
  17. package/dist/devtools-client/logs/index.html +1 -1
  18. package/dist/devtools-client/queries/index.html +1 -1
  19. package/dist/module.d.mts +29 -105
  20. package/dist/module.json +2 -2
  21. package/dist/module.mjs +329 -221
  22. package/dist/runtime/auth0/vue/index.d.ts +3 -3
  23. package/dist/runtime/better-auth/nuxt/middleware.d.ts +0 -6
  24. package/dist/runtime/better-auth/nuxt/middleware.js +4 -5
  25. package/dist/runtime/better-auth/nuxt/proxy.d.ts +18 -2
  26. package/dist/runtime/better-auth/nuxt/proxy.js +7 -7
  27. package/dist/runtime/better-auth/nuxt/server.d.ts +6 -6
  28. package/dist/runtime/better-auth/vue/auth-boundary.d.ts +1 -0
  29. package/dist/runtime/better-auth/vue/cross-domain.js +7 -2
  30. package/dist/runtime/better-auth/vue/hydration.d.ts +1 -1
  31. package/dist/runtime/better-auth/vue/index.d.ts +1 -1
  32. package/dist/runtime/better-auth/vue/index.js +1 -1
  33. package/dist/runtime/better-auth/vue/plugin.client.d.ts +1 -5
  34. package/dist/runtime/better-auth/vue/plugin.client.js +6 -10
  35. package/dist/runtime/better-auth/vue/plugin.server.d.ts +5 -16
  36. package/dist/runtime/better-auth/vue/plugin.server.js +3 -6
  37. package/dist/runtime/better-auth/vue/redirect.d.ts +2 -14
  38. package/dist/runtime/better-auth/vue/{use-auth.d.ts → use-better-auth.d.ts} +31 -11
  39. package/dist/runtime/better-auth/vue/{use-auth.js → use-better-auth.js} +2 -2
  40. package/dist/runtime/clerk/vue/index.d.ts +4 -4
  41. package/dist/runtime/nuxt/app.d.ts +48 -0
  42. package/dist/runtime/nuxt/app.js +8 -0
  43. package/dist/runtime/nuxt/composables/use-async-paginated-query.d.ts +88 -0
  44. package/dist/runtime/nuxt/composables/use-async-paginated-query.js +90 -0
  45. package/dist/runtime/nuxt/composables/use-async-query.d.ts +7 -16
  46. package/dist/runtime/nuxt/composables/use-async-query.js +14 -9
  47. package/dist/runtime/nuxt/config.d.ts +11 -0
  48. package/dist/runtime/nuxt/config.js +1 -0
  49. package/dist/runtime/nuxt/index.d.ts +2 -5
  50. package/dist/runtime/polar/vue/components.d.ts +8 -1
  51. package/dist/runtime/polar/vue/components.js +2 -2
  52. package/dist/runtime/vue/auth/index.d.ts +4 -4
  53. package/dist/runtime/vue/client.d.ts +5 -57
  54. package/dist/runtime/vue/client.js +2 -0
  55. package/dist/runtime/vue/components/convex-image.d.ts +50 -0
  56. package/dist/runtime/vue/components/convex-image.js +21 -0
  57. package/dist/runtime/vue/composables/use-connection-state.d.ts +1 -0
  58. package/dist/runtime/vue/composables/use-paginated-query.d.ts +5 -1
  59. package/dist/runtime/vue/composables/use-paginated-query.js +2 -2
  60. package/dist/runtime/vue/composables/use-query.d.ts +2 -0
  61. package/dist/runtime/vue/composables/use-subscription.d.ts +1 -15
  62. package/dist/runtime/vue/composables/use-upload-queue.d.ts +2 -3
  63. package/dist/runtime/vue/hydration.d.ts +3 -24
  64. package/dist/runtime/vue/index.d.ts +2 -2
  65. package/dist/runtime/vue/index.js +1 -0
  66. package/dist/runtime/vue/plugin.js +1 -1
  67. package/dist/runtime/vue/provide.d.ts +5 -5
  68. package/dist/types.d.mts +2 -2
  69. package/package.json +52 -16
  70. package/dist/devtools-client/_nuxt/builds/meta/23303226-2230-4d14-87ce-87b0f562de6c.json +0 -1
  71. package/dist/devtools-client/_nuxt/error-404.BpRUKU69.css +0 -1
  72. package/dist/devtools-client/_nuxt/error-500.DuDYJ5TI.css +0 -1
  73. package/dist/devtools-client/_nuxt/queries.BmISPDaV.css +0 -1
@@ -4,12 +4,12 @@ import { type ConvexAuthState, type IConvexVueClient } from '../../vue/auth/inde
4
4
  * Options for {@link provideConvexAuthFromAuth0} / `<ConvexProviderWithAuth0>`.
5
5
  */
6
6
  export interface ConvexProviderWithAuth0Options {
7
- /** Convex client to authenticate. Defaults to the provided {@link useConvex} client. */
7
+ /** Convex client to authenticate. Defaults to the client `useConvex()` returns. */
8
8
  client?: IConvexVueClient;
9
9
  }
10
10
  /**
11
11
  * The composable form of {@link ConvexProviderWithAuth0} — provides a
12
- * {@link ConvexVueClient} authenticated with Auth0.
12
+ * {@link client!ConvexVueClient | ConvexVueClient} authenticated with Auth0.
13
13
  *
14
14
  * It must be called in an app wrapped by a configured Auth0 plugin from
15
15
  * `@auth0/auth0-vue`.
@@ -29,7 +29,7 @@ export interface ConvexProviderWithAuth0Options {
29
29
  */
30
30
  export declare function provideConvexAuthFromAuth0(options?: ConvexProviderWithAuth0Options): ConvexAuthState;
31
31
  /**
32
- * A wrapper Vue component which provides a {@link ConvexVueClient}
32
+ * A wrapper Vue component which provides a {@link client!ConvexVueClient | ConvexVueClient}
33
33
  * authenticated with Auth0 — the component form of
34
34
  * {@link provideConvexAuthFromAuth0}. Renders its default slot once Convex
35
35
  * auth is wired.
@@ -12,11 +12,5 @@
12
12
  * </script>
13
13
  * ```
14
14
  */
15
- interface GuardedRoute {
16
- path: string;
17
- fullPath: string;
18
- }
19
- /** Exported for unit tests — `import.meta.server` is compile-time. @internal */
20
- export declare function serverGuard(to: GuardedRoute, loginPath: string): Promise<string | false | void | import("vue-router").RouteLocationAsRelativeGeneric | import("vue-router").RouteLocationAsPathGeneric | import("vue-router").NavigationFailure>;
21
15
  declare const _default: import("nuxt/app").RouteMiddleware;
22
16
  export default _default;
@@ -1,15 +1,14 @@
1
1
  import { defineNuxtRouteMiddleware, navigateTo, useNuxtApp, useRequestEvent, useRuntimeConfig } from "#app";
2
2
  import { watch } from "vue";
3
- import { useAuth } from "../vue/use-auth.js";
3
+ import { useBetterAuth } from "../vue/use-better-auth.js";
4
4
  import { convexAuth } from "./server.js";
5
5
  function loginTarget(to, loginPath) {
6
6
  return { path: loginPath, query: { redirect: to.fullPath } };
7
7
  }
8
8
  export async function serverGuard(to, loginPath) {
9
- const event = useRequestEvent();
10
- if (!event) return;
11
9
  const nuxtApp = useNuxtApp();
12
- const authed = await convexAuth(event).isAuthenticated();
10
+ const event = useRequestEvent();
11
+ const authed = event ? await convexAuth(event).isAuthenticated() : false;
13
12
  if (!authed && to.path !== loginPath) {
14
13
  return nuxtApp.runWithContext(() => navigateTo(loginTarget(to, loginPath)));
15
14
  }
@@ -33,7 +32,7 @@ export default defineNuxtRouteMiddleware(async (to) => {
33
32
  if (import.meta.server) {
34
33
  return serverGuard(to, loginPath);
35
34
  }
36
- const { session } = useAuth();
35
+ const { session } = useBetterAuth();
37
36
  if (session.value.isPending) {
38
37
  await waitForSession(() => session.value.isPending);
39
38
  }
@@ -1,6 +1,22 @@
1
1
  /**
2
- * Proxy all /api/auth/* requests to the Convex site URL.
3
- * This keeps auth cookies on the same origin (no CORS issues).
2
+ * Proxy all `${convex.authRoute}/**` requests (default `/api/auth/**`) to the
3
+ * Convex site URL. This keeps auth cookies on the same origin (no CORS issues).
4
+ *
5
+ * The site URL is `convexAuth`'s to resolve: the private `runtimeConfig.convex.siteUrl`,
6
+ * then the public one, then the environment — so a container built without it and
7
+ * started with `NUXT_PUBLIC_CONVEX_SITE_URL` works. Reading only the private key here
8
+ * used to fail every auth request in exactly that deployment.
9
+ *
10
+ * The method list matches the nuxt-security route rule the module registers on this
11
+ * route; enforcing it here too keeps the proxy closed to `PUT`/`DELETE` probes when
12
+ * nuxt-security is not installed.
13
+ *
14
+ * The path check: h3 routes the request's raw path, and the handler forwards the
15
+ * URL-normalised one. `/api/auth/../../x` (or its `%2e%2e` spelling) matches this
16
+ * route and normalises to `/x`, which the proxy would send to the site origin —
17
+ * any HTTP action on the deployment, reached through the app's origin with the
18
+ * app's cookies attached. Next.js normalises before routing, so upstream's
19
+ * handler never sees such a path; Nitro does not, so it is refused here.
4
20
  */
5
21
  declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<Response>>;
6
22
  export default _default;
@@ -1,11 +1,11 @@
1
- import { defineEventHandler } from "h3";
2
- import { useRuntimeConfig } from "#imports";
1
+ import { assertMethod, createError, defineEventHandler, toWebRequest } from "h3";
3
2
  import { convexAuth } from "./server.js";
4
3
  export default defineEventHandler(async (event) => {
5
- const config = useRuntimeConfig();
6
- const siteUrl = config.convex.siteUrl;
7
- if (!siteUrl) {
8
- throw new Error("[nuxt-convex-module] NUXT_PUBLIC_CONVEX_SITE_URL is not configured. Auth proxy cannot forward requests.");
4
+ assertMethod(event, ["GET", "HEAD", "POST", "OPTIONS"]);
5
+ const routed = event.path.split("?")[0];
6
+ const forwarded = new URL(toWebRequest(event).url).pathname;
7
+ if (forwarded !== routed) {
8
+ throw createError({ statusCode: 400, statusMessage: "Bad Request" });
9
9
  }
10
- return convexAuth(event, { convexSiteUrl: siteUrl }).handler();
10
+ return convexAuth(event).handler();
11
11
  });
@@ -1,11 +1,9 @@
1
1
  /**
2
2
  * Server-side Better Auth + Convex integration for Nuxt.
3
3
  *
4
- * Provides {@link convexAuth} for Nuxt server handlers.
5
- *
6
- * It accepts the H3
7
- * {@link H3Event} that is available in every Nuxt server route, API handler
8
- * and server middleware.
4
+ * Provides {@link convexAuth} for Nuxt server handlers: it takes the H3
5
+ * `H3Event` every Nuxt server route, API handler and server middleware
6
+ * receives, and returns a request-scoped, authenticated Convex client.
9
7
  *
10
8
  * @module better-auth/server
11
9
  */
@@ -30,7 +28,9 @@ export type ConvexAuthOptions = GetTokenOptions & {
30
28
  */
31
29
  convexUrl?: string;
32
30
  /**
33
- * Override the Convex site URL. Defaults to `NUXT_PUBLIC_CONVEX_SITE_URL`.
31
+ * Override the Convex site URL. Defaults to `runtimeConfig.convex.siteUrl`,
32
+ * then `runtimeConfig.public.convex.siteUrl`, then the
33
+ * `NUXT_PUBLIC_CONVEX_SITE_URL` process variable.
34
34
  */
35
35
  convexSiteUrl?: string;
36
36
  };
@@ -43,6 +43,7 @@ type EmptyObject = Record<string, never>;
43
43
  * @param props.isAuthError - Function to check if the error is auth related.
44
44
  *
45
45
  * @public
46
+ * @experimental May change in a minor release — see STABILITY.md.
46
47
  */
47
48
  export declare const AuthBoundary: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
48
49
  /**
@@ -21,10 +21,15 @@ export async function consumeCrossDomainOneTimeToken(options = {}) {
21
21
  }
22
22
  if (options.callbackRoute && normalizePathname(url.pathname) !== normalizePathname(options.callbackRoute)) {
23
23
  console.warn(
24
- `[nuxt-convex-module] ignoring cross-domain one-time token on "${url.pathname}" \u2014 consumption is restricted to "${options.callbackRoute}" (convex.betterAuth.crossDomainCallbackRoute).`
24
+ `[nuxt-convex-module] Ignoring cross-domain one-time token on "${url.pathname}" \u2014 consumption is restricted to "${options.callbackRoute}" (convex.betterAuth.crossDomainCallbackRoute).`
25
25
  );
26
26
  return;
27
27
  }
28
+ if (import.meta.dev && !options.callbackRoute) {
29
+ console.warn(
30
+ `[nuxt-convex-module] Exchanged a cross-domain one-time token on "${url.pathname}" with no \`convex.betterAuth.crossDomainCallbackRoute\` set \u2014 any page can complete sign-in. Restrict it to your callback route.`
31
+ );
32
+ }
28
33
  try {
29
34
  const result = await authClientWithCrossDomain.crossDomain.oneTimeToken.verify({
30
35
  token
@@ -41,7 +46,7 @@ export async function consumeCrossDomainOneTimeToken(options = {}) {
41
46
  await authClientWithCrossDomain.updateSession();
42
47
  }
43
48
  } catch (error) {
44
- console.warn("[nuxt-convex-module] failed to consume cross-domain one-time token", error);
49
+ console.warn("[nuxt-convex-module] Failed to consume cross-domain one-time token:", error);
45
50
  }
46
51
  }
47
52
  }
@@ -2,7 +2,7 @@ import type { FunctionReference } from 'convex/server';
2
2
  import { type ComputedRef, type MaybeRefOrGetter } from 'vue';
3
3
  import { type Preloaded } from '../../vue/hydration.js';
4
4
  /**
5
- * Auth-aware version of {@link usePreloadedQuery} for payloads returned by
5
+ * Auth-aware version of {@link client!usePreloadedQuery | usePreloadedQuery} for payloads returned by
6
6
  * `convexAuth(event).preloadAuthQuery(...)`.
7
7
  *
8
8
  * A Vue/Nuxt port of `@convex-dev/better-auth`'s `usePreloadedAuthQuery`
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * @module better-auth/client
6
6
  */
7
- export { useAuth, type UseAuthService, type AuthSession, type AuthUser } from './use-auth.js';
7
+ export { useBetterAuth, type UseBetterAuthReturn, type BetterAuthSession, type BetterAuthUser } from './use-better-auth.js';
8
8
  export { authClient, type AuthClient } from '#convex/auth-client';
9
9
  export { usePreloadedAuthQuery } from './hydration.js';
10
10
  export { consumeCrossDomainOneTimeToken, type ConsumeCrossDomainOneTimeTokenOptions } from './cross-domain.js';
@@ -1,4 +1,4 @@
1
- export { useAuth } from "./use-auth.js";
1
+ export { useBetterAuth } from "./use-better-auth.js";
2
2
  export { authClient } from "#convex/auth-client";
3
3
  export { usePreloadedAuthQuery } from "./hydration.js";
4
4
  export { consumeCrossDomainOneTimeToken } from "./cross-domain.js";
@@ -1,6 +1,2 @@
1
- import { ConvexVueClient } from '../../vue/client.js';
2
- type ConvexNuxtInjection = {
3
- convex?: ConvexVueClient;
4
- };
5
- declare const _default: import("nuxt/app").Plugin<ConvexNuxtInjection> & import("nuxt/app").ObjectPlugin<ConvexNuxtInjection>;
1
+ declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
6
2
  export default _default;
@@ -1,32 +1,28 @@
1
1
  import { defineNuxtPlugin, useRuntimeConfig, useState } from "#app";
2
2
  import { ConvexVueClient, ConvexClientKey } from "../../vue/client.js";
3
3
  import { ConvexAuthStateKey, createScopedConvexAuthState } from "../../vue/auth/index.js";
4
- import { useAuth } from "./use-auth.js";
4
+ import { CONVEX_INITIAL_TOKEN_KEY } from "../../nuxt/config.js";
5
+ import { useBetterAuth } from "./use-better-auth.js";
5
6
  import { consumeCrossDomainOneTimeToken } from "./cross-domain.js";
6
7
  export default defineNuxtPlugin({
7
8
  name: "nuxt-convex-module:better-auth:client",
8
9
  async setup(nuxtApp) {
9
10
  const { url, crossDomainCallbackRoute } = useRuntimeConfig().public.convex;
10
11
  if (!url) {
11
- console.warn("[nuxt-convex-module] No Convex URL configured for client plugin.");
12
- return { provide: {} };
12
+ console.warn("[nuxt-convex-module] No Convex deployment URL configured \u2014 client and auth not created. Set NUXT_PUBLIC_CONVEX_URL or `convex.url` in nuxt.config.");
13
+ return;
13
14
  }
14
15
  const client = new ConvexVueClient(url);
15
16
  nuxtApp.vueApp.provide(ConvexClientKey, client);
16
17
  await consumeCrossDomainOneTimeToken({
17
18
  callbackRoute: crossDomainCallbackRoute || void 0
18
19
  });
19
- const initialToken = useState("convex:initialToken", () => null);
20
+ const initialToken = useState(CONVEX_INITIAL_TOKEN_KEY, () => null);
20
21
  const { state, scope } = createScopedConvexAuthState({
21
22
  client,
22
- useAuth: () => useAuth(initialToken.value)
23
+ useAuth: () => useBetterAuth(initialToken.value)
23
24
  });
24
25
  nuxtApp.vueApp.provide(ConvexAuthStateKey, state);
25
26
  void scope;
26
- return {
27
- provide: {
28
- convex: client
29
- }
30
- };
31
27
  }
32
28
  });
@@ -1,24 +1,13 @@
1
- import { useState, useRequestEvent } from '#app';
2
- import { ConvexVueClient } from '../../vue/client.js';
3
- type ConvexNuxtInjection = {
4
- convex?: ConvexVueClient;
5
- };
6
- /**
7
- * Prefetch the Convex JWT for SSR and stash it in `initialToken`.
8
- *
9
- * Exported for unit testing.
10
- */
11
- export declare function prefetchAuthToken(event: ReturnType<typeof useRequestEvent>, initialToken: ReturnType<typeof useState<string | null>>): Promise<void>;
12
1
  /**
13
2
  * Server-side Better Auth bootstrap.
14
3
  *
15
4
  * Mirrors the Next.js parity layer that calls `getToken()` from the root
16
5
  * server layout and passes it as `initialToken` to `ConvexBetterAuthProvider`.
17
6
  *
18
- * The token is stashed into a Nuxt `useState('convex:initialToken')` so the
19
- * client plugin can hand it to `useAuth(initialToken)` before the first
20
- * Convex `setAuth` call — avoiding an extra Better Auth round-trip on first
21
- * paint.
7
+ * The token is stashed into a Nuxt `useState` (`CONVEX_INITIAL_TOKEN_KEY`) so
8
+ * the client plugin can hand it to `useBetterAuth(initialToken)` before the
9
+ * first Convex `setAuth` call — avoiding an extra Better Auth round-trip on
10
+ * first paint.
22
11
  */
23
- declare const _default: import("nuxt/app").Plugin<ConvexNuxtInjection> & import("nuxt/app").ObjectPlugin<ConvexNuxtInjection>;
12
+ declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
24
13
  export default _default;
@@ -2,11 +2,9 @@ import { computed } from "vue";
2
2
  import { setResponseHeader } from "h3";
3
3
  import { defineNuxtPlugin, useRuntimeConfig, useState, useRequestEvent } from "#app";
4
4
  import { ConvexVueClient, ConvexClientKey } from "../../vue/client.js";
5
+ import { CONVEX_INITIAL_TOKEN_KEY } from "../../nuxt/config.js";
5
6
  import { convexAuth } from "../nuxt/server.js";
6
7
  import { ConvexAuthStateKey } from "../../vue/auth/index.js";
7
- function buildProvide(ssrClient) {
8
- return ssrClient ? { provide: { convex: ssrClient } } : { provide: {} };
9
- }
10
8
  export async function prefetchAuthToken(event, initialToken) {
11
9
  try {
12
10
  const token = await convexAuth(event).getToken();
@@ -21,7 +19,7 @@ export async function prefetchAuthToken(event, initialToken) {
21
19
  export default defineNuxtPlugin({
22
20
  name: "nuxt-convex-module:better-auth:server",
23
21
  async setup(nuxtApp) {
24
- const initialToken = useState("convex:initialToken", () => null);
22
+ const initialToken = useState(CONVEX_INITIAL_TOKEN_KEY, () => null);
25
23
  const url = useRuntimeConfig().public.convex.url;
26
24
  const ssrClient = url ? new ConvexVueClient(url) : void 0;
27
25
  if (ssrClient) {
@@ -34,9 +32,8 @@ export default defineNuxtPlugin({
34
32
  };
35
33
  nuxtApp.vueApp.provide(ConvexAuthStateKey, ssrAuthState);
36
34
  const event = useRequestEvent();
37
- if (event) {
35
+ if (event && !import.meta.prerender) {
38
36
  await prefetchAuthToken(event, initialToken);
39
37
  }
40
- return buildProvide(ssrClient);
41
38
  }
42
39
  });
@@ -1,15 +1,3 @@
1
- /**
2
- * Safe handling of the `?redirect=` destination the `auth` route middleware
3
- * attaches when it sends an unauthenticated visitor to the login page.
4
- *
5
- * The middleware only ever writes a router path there, but the query is part
6
- * of a URL anyone can craft: a link to `/login?redirect=https://evil.example`
7
- * turns a login page that navigates to `route.query.redirect` verbatim into an
8
- * open redirect — a phishing primitive that borrows the app's own domain, and
9
- * one that carries whatever the app appends to the destination.
10
- *
11
- * @module better-auth/redirect
12
- */
13
1
  /**
14
2
  * Validate a post-sign-in redirect destination, returning `fallback` unless it
15
3
  * is a same-origin path.
@@ -21,10 +9,10 @@
21
9
  * ```vue
22
10
  * <script setup lang="ts">
23
11
  * const route = useRoute()
24
- * const { signIn } = useAuth()
12
+ * const { client } = useBetterAuth()
25
13
  *
26
14
  * async function onSubmit() {
27
- * await signIn.email({ email, password })
15
+ * await client.signIn.email({ email, password })
28
16
  * // '/dashboard' survives; 'https://evil.example' becomes '/'.
29
17
  * await navigateTo(resolveAuthRedirect(route.query.redirect))
30
18
  * }
@@ -27,7 +27,9 @@ declare const useClientSession: () => Readonly<import("vue").Ref<{
27
27
  readonly isPending: boolean;
28
28
  readonly isRefetching: boolean;
29
29
  readonly error: import("better-auth/client").BetterFetchError | null;
30
- readonly refetch: (queryParams?: {
30
+ readonly refetch: (queryParams
31
+ /** The Better Auth client from `#convex/auth-client` — sign-in, sign-out and every plugin flow live here. */
32
+ ?: {
31
33
  query?: import("better-auth").SessionQueryParams;
32
34
  } | undefined) => Promise<void>;
33
35
  }, {
@@ -56,37 +58,55 @@ declare const useClientSession: () => Readonly<import("vue").Ref<{
56
58
  readonly isPending: boolean;
57
59
  readonly isRefetching: boolean;
58
60
  readonly error: import("better-auth/client").BetterFetchError | null;
59
- readonly refetch: (queryParams?: {
61
+ readonly refetch: (queryParams
62
+ /** The Better Auth client from `#convex/auth-client` — sign-in, sign-out and every plugin flow live here. */
63
+ ?: {
60
64
  query?: import("better-auth").SessionQueryParams;
61
65
  } | undefined) => Promise<void>;
62
66
  }>>;
63
- export type AuthSession = ReturnType<typeof useClientSession>;
67
+ export type BetterAuthSession = ReturnType<typeof useClientSession>;
64
68
  /** The signed-in user (loose — exact fields depend on your auth schema). */
65
- export type AuthUser = {
69
+ export type BetterAuthUser = {
66
70
  id: string;
67
71
  email: string;
68
72
  name: string;
69
73
  } & Record<string, unknown>;
70
- export interface UseAuthService {
74
+ /** What `useBetterAuth()` returns. */
75
+ export interface UseBetterAuthReturn {
76
+ /** `true` until the session is known and no prefetched token covers the gap. */
71
77
  isLoading: ComputedRef<boolean>;
78
+ /** `true` when Better Auth reports a session, or a token is cached while it reloads. */
72
79
  isAuthenticated: ComputedRef<boolean>;
80
+ /** Convex's token fetcher: the Better Auth JWT for the current session, or `null`. */
73
81
  fetchAccessToken: AuthTokenFetcher;
82
+ /** The Better Auth client from `#convex/auth-client` — sign-in, sign-out and every plugin flow live here. */
74
83
  client: AuthClient;
75
- session: AuthSession;
84
+ /** Better Auth's own `useSession()` ref: `{ data, isPending, error }`. */
85
+ session: BetterAuthSession;
76
86
  /** The current user, or `null` when signed out / still loading. */
77
- user: ComputedRef<AuthUser | null>;
87
+ user: ComputedRef<BetterAuthUser | null>;
88
+ /** The session id (or user id); changes when the signed-in identity changes. */
78
89
  authVersion: ComputedRef<string | null>;
79
90
  }
80
91
  /**
81
- * Unified Better Auth service for the Vue/Nuxt runtime.
92
+ * The Better Auth service for the Vue/Nuxt runtime.
82
93
  *
83
94
  * Returns the full Better Auth client, the reactive session wrapper, and the
84
95
  * Convex-compatible auth state used by the packaged auth plugin.
85
96
  *
86
97
  * @param initialToken - Optional preloaded token, used once per app lifetime
87
98
  * to avoid a round-trip on initial load (e.g. from SSR).
99
+ *
100
+ * @example
101
+ * ```vue
102
+ * <script setup lang="ts">
103
+ * const { user, client, isAuthenticated } = useBetterAuth()
104
+ *
105
+ * const signOut = () => client.signOut()
106
+ * </script>
107
+ * ```
108
+ *
109
+ * @public
88
110
  */
89
- export declare function useAuth(initialToken?: string | null): UseAuthService;
90
- /** Reset module-level token cache — intended for tests only. */
91
- export declare function __resetUseAuthForTests(): void;
111
+ export declare function useBetterAuth(initialToken?: string | null): UseBetterAuthReturn;
92
112
  export {};
@@ -7,7 +7,7 @@ let pendingTokenVersion = null;
7
7
  let initialTokenUsed = false;
8
8
  const PENDING_AUTH_VERSION = "__pending__";
9
9
  const useClientSession = () => authClient.useSession();
10
- export function useAuth(initialToken) {
10
+ export function useBetterAuth(initialToken) {
11
11
  if (!initialTokenUsed && initialToken) {
12
12
  cachedToken.value = initialToken;
13
13
  cachedTokenVersion = PENDING_AUTH_VERSION;
@@ -74,7 +74,7 @@ export function useAuth(initialToken) {
74
74
  authVersion
75
75
  };
76
76
  }
77
- export function __resetUseAuthForTests() {
77
+ export function __resetUseBetterAuthForTests() {
78
78
  cachedToken.value = null;
79
79
  cachedTokenVersion = null;
80
80
  pendingToken = null;
@@ -16,15 +16,15 @@ export type UseAuth = () => {
16
16
  * Options for {@link provideConvexAuthFromClerk} / `<ConvexProviderWithClerk>`.
17
17
  */
18
18
  export interface ConvexProviderWithClerkOptions {
19
- /** Convex client to authenticate. Defaults to the provided {@link useConvex} client. */
19
+ /** Convex client to authenticate. Defaults to the client `useConvex()` returns. */
20
20
  client?: IConvexVueClient;
21
21
  /** Clerk's `useAuth` composable. Defaults to `useAuth` from `@clerk/vue`. */
22
22
  useAuth?: UseAuth;
23
23
  }
24
24
  /**
25
- * A composable which provides a {@link ConvexVueClient}
25
+ * A composable which provides a {@link client!ConvexVueClient | ConvexVueClient}
26
26
  * authenticated with Clerk, exposing the reactive auth state to descendants
27
- * via {@link useConvexAuth} — the Vue translation of wrapping the app in
27
+ * via {@link client!useConvexAuth | useConvexAuth} — the Vue translation of wrapping the app in
28
28
  * `convex/react-clerk`'s `<ConvexProviderWithClerk>`.
29
29
  *
30
30
  * Call it in a top-level component's `setup`. The app must be wrapped by a
@@ -47,7 +47,7 @@ export interface ConvexProviderWithClerkOptions {
47
47
  */
48
48
  export declare function provideConvexAuthFromClerk(options?: ConvexProviderWithClerkOptions): ConvexAuthState;
49
49
  /**
50
- * A wrapper Vue component which provides a {@link ConvexVueClient}
50
+ * A wrapper Vue component which provides a {@link client!ConvexVueClient | ConvexVueClient}
51
51
  * authenticated with Clerk — the component form of
52
52
  * {@link provideConvexAuthFromClerk}, kept as a drop-in parity port of
53
53
  * `convex/react-clerk`'s `<ConvexProviderWithClerk>`. Renders its default
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Composables that need the Nuxt app context (`#app`) — the half of the
3
+ * package that runs in a Nuxt app but not in plain Vue.
4
+ *
5
+ * This module contains {@link useAsyncQuery} and its paginated form
6
+ * {@link useAsyncPaginatedQuery}: server-rendered Convex data that upgrades
7
+ * to a live subscription after hydration.
8
+ *
9
+ * ## Usage
10
+ *
11
+ * **Default — auto-imported.** In any page, component or composable, call it
12
+ * with no import; its types are auto-imported too:
13
+ *
14
+ * ```vue
15
+ * <script setup lang="ts">
16
+ * import { api } from '#convex/api'
17
+ *
18
+ * const { data: messages, status } = useAsyncQuery(api.messages.list, {})
19
+ * // `AsyncQueryStatus`, `AsyncQueryReturn`, … resolve without an import as well:
20
+ * const label = (s: AsyncQueryStatus) => s === 'pending' ? 'Loading…' : ''
21
+ * </script>
22
+ * ```
23
+ *
24
+ * **Explicit import — this subpath.** For a project that turns auto-imports
25
+ * off, a file outside the app's auto-import scope, or an editor that wants
26
+ * the import spelled out:
27
+ *
28
+ * ```ts
29
+ * import { useAsyncQuery } from 'nuxt-convex-module/app'
30
+ * ```
31
+ *
32
+ * **Types.** From `#imports` (Nuxt's auto-import barrel) or from this subpath,
33
+ * whichever your file already uses:
34
+ *
35
+ * ```ts
36
+ * import type { AsyncQueryReturn } from '#imports'
37
+ * import type { AsyncQueryReturn } from 'nuxt-convex-module/app'
38
+ *
39
+ * const messages: AsyncQueryReturn<Doc<'messages'>[]> = useAsyncQuery(api.messages.list, {})
40
+ * ```
41
+ *
42
+ * Before 1.0 the composable was auto-imported but reachable from no subpath,
43
+ * so neither the explicit form nor the types could be written at all.
44
+ *
45
+ * @module app
46
+ */
47
+ export { useAsyncQuery, useConvexAsyncQuery, type AsyncQueryData, type AsyncQueryOptions, type AsyncQueryReturn, type AsyncQueryStatus, } from './composables/use-async-query.js';
48
+ export { useAsyncPaginatedQuery, useConvexAsyncPaginatedQuery, type AsyncPaginatedQueryData, type AsyncPaginatedQueryOptions, type AsyncPaginatedQueryReturn, } from './composables/use-async-paginated-query.js';
@@ -0,0 +1,8 @@
1
+ export {
2
+ useAsyncQuery,
3
+ useConvexAsyncQuery
4
+ } from "./composables/use-async-query.js";
5
+ export {
6
+ useAsyncPaginatedQuery,
7
+ useConvexAsyncPaginatedQuery
8
+ } from "./composables/use-async-paginated-query.js";
@@ -0,0 +1,88 @@
1
+ import { type ComputedRef, type MaybeRefOrGetter } from 'vue';
2
+ import { type PaginatedQueryArgs, type PaginatedQueryItem, type PaginatedQueryReference, type PaginationStatus } from '../../vue/composables/use-paginated-query.js';
3
+ import { type AsyncQueryOptions } from './use-async-query.js';
4
+ /**
5
+ * Options for {@link useAsyncPaginatedQuery}: `usePaginatedQuery`'s
6
+ * `initialNumItems` plus the SSR options of {@link AsyncQueryOptions}.
7
+ *
8
+ * @public
9
+ */
10
+ export interface AsyncPaginatedQueryOptions extends Pick<AsyncQueryOptions, 'key' | 'server' | 'lazy' | 'token'> {
11
+ /** How many items the first page holds — on the server and on the client. */
12
+ initialNumItems: number;
13
+ }
14
+ /**
15
+ * The reactive half of {@link AsyncPaginatedQueryReturn}: `usePaginatedQuery`'s
16
+ * fields plus the `error` and `refresh` of the Nuxt data contract.
17
+ *
18
+ * @public
19
+ */
20
+ export interface AsyncPaginatedQueryData<Item> {
21
+ /**
22
+ * The rows: the server-rendered first page until the live subscription
23
+ * delivers its own, then every loaded page, live. The server page is
24
+ * shown for the initial args only — after an args change the list is
25
+ * empty until the new first page arrives.
26
+ */
27
+ results: ComputedRef<Item[]>;
28
+ /**
29
+ * `usePaginatedQuery`'s status. Before the live subscription has its first
30
+ * page it is derived from the server page: `'CanLoadMore'` or `'Exhausted'`.
31
+ */
32
+ status: ComputedRef<PaginationStatus>;
33
+ /** `true` while no page — server or live — is available yet, or more rows are loading. */
34
+ isLoading: ComputedRef<boolean>;
35
+ /** The SSR fetch error or the live subscription's, `null` when none. Never thrown. */
36
+ error: ComputedRef<Error | null>;
37
+ /**
38
+ * Fetch `numItems` more rows. Takes effect once the live subscription has
39
+ * its first page (`status` no longer derived from the server page).
40
+ */
41
+ loadMore: (numItems: number) => void;
42
+ /** Re-run the server-side first-page fetch (client-side it is a no-op — the subscription is live). */
43
+ refresh: (opts?: {
44
+ dedupe?: 'cancel' | 'defer';
45
+ }) => Promise<void>;
46
+ }
47
+ /**
48
+ * Result of {@link useAsyncPaginatedQuery}: awaitable like `useAsyncData`, and
49
+ * the refs of {@link AsyncPaginatedQueryData}.
50
+ *
51
+ * @public
52
+ */
53
+ export interface AsyncPaginatedQueryReturn<Item> extends PromiseLike<AsyncPaginatedQueryData<Item>>, AsyncPaginatedQueryData<Item> {
54
+ }
55
+ /**
56
+ * A paginated Convex query the Nuxt way: the first page is fetched during SSR
57
+ * and hydrated from the payload, then {@link usePaginatedQuery} takes over on
58
+ * the client — live rows and `loadMore`, no loading flash for the first page.
59
+ *
60
+ * @example
61
+ * ```vue
62
+ * <script setup lang="ts">
63
+ * import { api } from '#convex/api'
64
+ *
65
+ * const { results, status, loadMore } = useAsyncPaginatedQuery(
66
+ * api.messages.list,
67
+ * {},
68
+ * { initialNumItems: 20 },
69
+ * )
70
+ * </script>
71
+ * ```
72
+ *
73
+ * The payload entry is keyed on the query name, the *initial* args and
74
+ * `initialNumItems` (override with `options.key`). Client-side navigation does
75
+ * not fetch a page over HTTP: the subscription opens straight away, and the
76
+ * server page only matters for the first paint.
77
+ *
78
+ * @param query - a `FunctionReference` for the public paginated query.
79
+ * @param args - the query's arguments without `paginationOpts`, or `'skip'`.
80
+ * Accepts a ref, computed, or getter.
81
+ * @param options - {@link AsyncPaginatedQueryOptions}.
82
+ * @returns An awaitable {@link AsyncPaginatedQueryReturn}.
83
+ *
84
+ * @public
85
+ */
86
+ export declare function useAsyncPaginatedQuery<Query extends PaginatedQueryReference>(query: Query, args: MaybeRefOrGetter<PaginatedQueryArgs<Query> | 'skip'>, options: AsyncPaginatedQueryOptions): AsyncPaginatedQueryReturn<PaginatedQueryItem<Query>>;
87
+ /** @public */
88
+ export declare const useConvexAsyncPaginatedQuery: typeof useAsyncPaginatedQuery;