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
@@ -0,0 +1,90 @@
1
+ import { useAsyncData } from "#app";
2
+ import { computed, toValue } from "vue";
3
+ import { getFunctionName } from "convex/server";
4
+ import { convexToJson, jsonToConvex } from "convex/values";
5
+ import {
6
+ usePaginatedQuery
7
+ } from "../../vue/composables/use-paginated-query.js";
8
+ import { fetchQuery } from "../index.js";
9
+ import { useAsyncQueryContext } from "./use-async-query.js";
10
+ export function useAsyncPaginatedQuery(query, args, options) {
11
+ const { initialNumItems, server = true, lazy = false, token } = options;
12
+ const queryName = getFunctionName(query);
13
+ const initialArgs = toValue(args);
14
+ const key = options.key ?? defaultAsyncPaginatedQueryKey(queryName, initialArgs, initialNumItems);
15
+ const { client, deploymentUrl, resolveToken } = useAsyncQueryContext(token);
16
+ const asyncData = useAsyncData(
17
+ key,
18
+ async () => {
19
+ const currentArgs = toValue(args);
20
+ if (currentArgs === "skip" || !import.meta.server) {
21
+ return null;
22
+ }
23
+ if (!deploymentUrl) {
24
+ throw new Error(
25
+ "`useAsyncPaginatedQuery` could not fetch during SSR: no Convex deployment URL is configured. Set NUXT_PUBLIC_CONVEX_URL or `convex.url` in nuxt.config."
26
+ );
27
+ }
28
+ const result2 = await fetchQuery(
29
+ query,
30
+ { ...currentArgs, paginationOpts: { numItems: initialNumItems, cursor: null } },
31
+ { token: await resolveToken(), url: deploymentUrl }
32
+ );
33
+ return { page: convexToJson(result2.page), isDone: result2.isDone };
34
+ },
35
+ { server, lazy, deep: false, immediate: initialArgs !== "skip" }
36
+ );
37
+ const payloadPage = computed(() => {
38
+ const entry = asyncData.data.value;
39
+ return entry ? jsonToConvex(entry.page) : void 0;
40
+ });
41
+ const live = !import.meta.server && client ? usePaginatedQuery(query, args, { initialNumItems }) : void 0;
42
+ const liveState = computed(() => {
43
+ if (!live) return void 0;
44
+ try {
45
+ return { results: live.results.value, status: live.status.value, error: null };
46
+ } catch (thrown) {
47
+ return { results: [], status: "LoadingFirstPage", error: thrown };
48
+ }
49
+ });
50
+ const liveHasPage = computed(() => liveState.value !== void 0 && liveState.value.status !== "LoadingFirstPage");
51
+ const clientError = computed(() => {
52
+ if (import.meta.server || client || toValue(args) === "skip") return null;
53
+ return new Error(
54
+ "`useAsyncPaginatedQuery` could not start on the client: no Convex client is available. Set NUXT_PUBLIC_CONVEX_URL or `convex.url` in nuxt.config."
55
+ );
56
+ });
57
+ const initialArgsJson = argsJson(initialArgs);
58
+ let payloadRetired = false;
59
+ const payloadApplies = computed(() => {
60
+ if (liveHasPage.value || argsJson(toValue(args)) !== initialArgsJson) payloadRetired = true;
61
+ return !payloadRetired && payloadPage.value !== void 0;
62
+ });
63
+ const results = computed(() => {
64
+ if (liveHasPage.value) return liveState.value.results;
65
+ return payloadApplies.value ? payloadPage.value : [];
66
+ });
67
+ const status = computed(() => {
68
+ if (liveHasPage.value) return liveState.value.status;
69
+ if (payloadApplies.value) return asyncData.data.value.isDone ? "Exhausted" : "CanLoadMore";
70
+ return "LoadingFirstPage";
71
+ });
72
+ const isLoading = computed(() => status.value === "LoadingFirstPage" || status.value === "LoadingMore");
73
+ const error = computed(
74
+ () => liveState.value?.error ?? clientError.value ?? asyncData.error.value ?? null
75
+ );
76
+ const loadMore = (numItems) => {
77
+ live?.loadMore(numItems);
78
+ };
79
+ const refresh = (opts) => asyncData.refresh(opts);
80
+ const result = { results, status, isLoading, error, loadMore, refresh };
81
+ const promise = Promise.resolve(asyncData).then(() => result);
82
+ return Object.assign(promise, result);
83
+ }
84
+ function argsJson(args) {
85
+ return args === "skip" ? '"skip"' : JSON.stringify(convexToJson(args ?? {}));
86
+ }
87
+ export function defaultAsyncPaginatedQueryKey(queryName, initialArgs, initialNumItems) {
88
+ return `convex:paginated:${queryName}:${argsJson(initialArgs)}:${initialNumItems}`;
89
+ }
90
+ export const useConvexAsyncPaginatedQuery = useAsyncPaginatedQuery;
@@ -1,15 +1,3 @@
1
- /**
2
- * Nuxt-idiomatic data fetching for Convex queries.
3
- *
4
- * {@link useAsyncQuery} is a Vue/Nuxt-only addition (no `convex/react`
5
- * counterpart — see PARITY.md): it marries Nuxt's `useAsyncData` model with
6
- * Convex's live queries. During SSR the query runs over HTTP and the result is
7
- * embedded in the Nuxt payload; after hydration the composable upgrades to the
8
- * WebSocket subscription, so the page paints with server data and stays live —
9
- * no loading flash, no client refetch.
10
- *
11
- * @module
12
- */
13
1
  import { type ComputedRef, type MaybeRefOrGetter } from 'vue';
14
2
  import type { FunctionArgs, FunctionReference, FunctionReturnType } from 'convex/server';
15
3
  /**
@@ -94,7 +82,13 @@ export interface AsyncQueryReturn<T> extends PromiseLike<AsyncQueryData<T>> {
94
82
  dedupe?: 'cancel' | 'defer';
95
83
  }) => Promise<void>;
96
84
  }
97
- type AsyncQueryData<T> = Pick<AsyncQueryReturn<T>, 'data' | 'error' | 'status' | 'refresh'>;
85
+ /**
86
+ * The reactive half of {@link AsyncQueryReturn} — what `await useAsyncQuery(...)`
87
+ * resolves to, and the shape to annotate a value passed on from the call site.
88
+ *
89
+ * @public
90
+ */
91
+ export type AsyncQueryData<T> = Pick<AsyncQueryReturn<T>, 'data' | 'error' | 'status' | 'refresh'>;
98
92
  /**
99
93
  * Load a Convex query the Nuxt way: fetched on the server during SSR,
100
94
  * hydrated through the Nuxt payload, then seamlessly upgraded to a live
@@ -137,8 +131,5 @@ type AsyncQueryData<T> = Pick<AsyncQueryReturn<T>, 'data' | 'error' | 'status' |
137
131
  * @public
138
132
  */
139
133
  export declare function useAsyncQuery<Query extends FunctionReference<'query'>>(query: Query, args?: MaybeRefOrGetter<FunctionArgs<Query> | 'skip'>, options?: AsyncQueryOptions): AsyncQueryReturn<FunctionReturnType<Query>>;
140
- /** Payload key for a query + initial args. Exported for tests. @internal */
141
- export declare function defaultAsyncQueryKey(queryName: string, initialArgs: unknown): string;
142
134
  /** @public */
143
135
  export declare const useConvexAsyncQuery: typeof useAsyncQuery;
144
- export {};
@@ -4,6 +4,7 @@ import { getFunctionName, makeFunctionReference } from "convex/server";
4
4
  import { convexToJson, jsonToConvex } from "convex/values";
5
5
  import { useConvex } from "../../vue/client.js";
6
6
  import { useConvexQueries } from "../../vue/composables/use-queries.js";
7
+ import { CONVEX_INITIAL_TOKEN_KEY } from "../config.js";
7
8
  import { fetchQuery } from "../index.js";
8
9
  export function useAsyncQuery(query, args, options = {}) {
9
10
  const { server = true, lazy = false, live = true, token } = options;
@@ -11,13 +12,7 @@ export function useAsyncQuery(query, args, options = {}) {
11
12
  const queryName = getFunctionName(queryReference);
12
13
  const initialArgs = toValue(args) ?? {};
13
14
  const key = options.key ?? defaultAsyncQueryKey(queryName, initialArgs);
14
- const initialToken = useState("convex:initialToken", () => null);
15
- const client = useConvex();
16
- const deploymentUrl = import.meta.server ? useRuntimeConfig().public.convex.url : "";
17
- const resolveToken = async () => {
18
- const resolved = typeof token === "function" ? await token() : token ?? initialToken.value;
19
- return resolved ?? void 0;
20
- };
15
+ const { client, deploymentUrl, resolveToken } = useAsyncQueryContext(token);
21
16
  const asyncData = useAsyncData(
22
17
  key,
23
18
  async () => {
@@ -28,7 +23,7 @@ export function useAsyncQuery(query, args, options = {}) {
28
23
  if (import.meta.server) {
29
24
  if (!deploymentUrl) {
30
25
  throw new Error(
31
- "`useAsyncQuery` could not fetch during SSR: no Convex deployment URL is configured. Set the `convex.url` module option or NUXT_PUBLIC_CONVEX_URL."
26
+ "`useAsyncQuery` could not fetch during SSR: no Convex deployment URL is configured. Set NUXT_PUBLIC_CONVEX_URL or `convex.url` in nuxt.config."
32
27
  );
33
28
  }
34
29
  const value2 = await fetchQuery(queryReference, currentArgs, {
@@ -39,7 +34,7 @@ export function useAsyncQuery(query, args, options = {}) {
39
34
  }
40
35
  if (!client) {
41
36
  throw new Error(
42
- "`useAsyncQuery` could not fetch on the client: no Convex client is available. Is the `convex.url` module option (or NUXT_PUBLIC_CONVEX_URL) configured?"
37
+ "`useAsyncQuery` could not fetch on the client: no Convex client is available. Set NUXT_PUBLIC_CONVEX_URL or `convex.url` in nuxt.config."
43
38
  );
44
39
  }
45
40
  const value = await client.query(queryReference, currentArgs);
@@ -97,6 +92,16 @@ export function useAsyncQuery(query, args, options = {}) {
97
92
  const promise = Promise.resolve(asyncData).then(() => result);
98
93
  return Object.assign(promise, result);
99
94
  }
95
+ export function useAsyncQueryContext(token) {
96
+ const initialToken = useState(CONVEX_INITIAL_TOKEN_KEY, () => null);
97
+ const client = useConvex();
98
+ const deploymentUrl = import.meta.server ? useRuntimeConfig().public.convex.url : "";
99
+ const resolveToken = async () => {
100
+ const resolved = typeof token === "function" ? await token() : token ?? initialToken.value;
101
+ return resolved ?? void 0;
102
+ };
103
+ return { client, deploymentUrl, resolveToken };
104
+ }
100
105
  export function defaultAsyncQueryKey(queryName, initialArgs) {
101
106
  const argsJson = initialArgs === "skip" ? '"skip"' : JSON.stringify(convexToJson(initialArgs ?? {}));
102
107
  return `convex:${queryName}:${argsJson}`;
@@ -1,3 +1,14 @@
1
+ /**
2
+ * Nuxt `useState` key the Better Auth server plugin stashes the SSR-prefetched
3
+ * Convex JWT under, read back by the client plugin and `useAsyncQuery`. Lives
4
+ * here, dependency-free, so the core composable can read the token without
5
+ * importing the integration.
6
+ */
7
+ export declare const CONVEX_INITIAL_TOKEN_KEY = "convex:initialToken";
8
+ /**
9
+ * The module's runtime config, tolerating a missing Nuxt context (a plain
10
+ * server import outside a request) by returning an empty object.
11
+ */
1
12
  export declare function getConvexRuntimeConfig(): {
2
13
  url: string | undefined;
3
14
  siteUrl: string | undefined;
@@ -1,4 +1,5 @@
1
1
  import { useRuntimeConfig } from "#imports";
2
+ export const CONVEX_INITIAL_TOKEN_KEY = "convex:initialToken";
2
3
  export function getConvexRuntimeConfig() {
3
4
  try {
4
5
  const config = useRuntimeConfig();
@@ -54,15 +54,12 @@ export type NuxtOptions = {
54
54
  token?: string;
55
55
  /**
56
56
  * The URL of the Convex deployment to use for the function call.
57
- * Defaults to `process.env.NUXT_PUBLIC_CONVEX_URL` if not provided.
57
+ * Defaults to `runtimeConfig.public.convex.url`, then to
58
+ * `process.env.NUXT_PUBLIC_CONVEX_URL`, if not provided.
58
59
  *
59
60
  * Explicitly passing undefined here (such as from missing ENV variables) will throw an error in the future.
60
61
  */
61
62
  url?: string;
62
- /**
63
- * @internal
64
- */
65
- adminToken?: string;
66
63
  /**
67
64
  * Skip validating that the Convex deployment URL looks like
68
65
  * `https://happy-animal-123.convex.cloud` or localhost.
@@ -48,10 +48,15 @@ export interface PolarComponentApi {
48
48
  }>;
49
49
  }
50
50
  /**
51
+ * Renders a link to the Polar customer portal for the signed-in user, where
52
+ * they manage their subscription.
53
+ *
51
54
  * @example
52
55
  * ```vue
53
56
  * <CustomerPortalLink>Manage subscription</CustomerPortalLink>
54
57
  * ```
58
+ *
59
+ * @public
55
60
  */
56
61
  export declare const CustomerPortalLink: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
57
62
  polarApi: {
@@ -86,6 +91,8 @@ export declare const CustomerPortalLink: import("vue").DefineComponent<import("v
86
91
  * Start free trial
87
92
  * </CheckoutLink>
88
93
  * ```
94
+ *
95
+ * @public
89
96
  */
90
97
  export declare const CheckoutLink: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
91
98
  polarApi: {
@@ -172,9 +179,9 @@ export declare const CheckoutLink: import("vue").DefineComponent<import("vue").E
172
179
  default: boolean;
173
180
  };
174
181
  }>> & Readonly<{}>, {
182
+ embed: boolean;
175
183
  lazy: boolean;
176
184
  metadata: Record<string, string>;
177
- embed: boolean;
178
185
  subscriptionId: string;
179
186
  trialInterval: "day" | "week" | "month" | "year" | null;
180
187
  trialIntervalCount: number | null;
@@ -13,7 +13,7 @@ export const CustomerPortalLink = defineComponent({
13
13
  const polarApi = props.polarApi ?? useConvexNamespace("billing");
14
14
  const generateCustomerPortalUrl = polarApi?.generateCustomerPortalUrl ? useAction(polarApi.generateCustomerPortalUrl) : void 0;
15
15
  const portalUrl = ref();
16
- if (import.meta.client && generateCustomerPortalUrl) {
16
+ if (!import.meta.server && generateCustomerPortalUrl) {
17
17
  watch(
18
18
  () => props.returnUrl,
19
19
  (returnUrl) => {
@@ -55,7 +55,7 @@ export const CheckoutLink = defineComponent({
55
55
  const generateCheckoutLink = polarApi?.generateCheckoutLink ? useAction(polarApi.generateCheckoutLink) : void 0;
56
56
  const checkoutLink = ref();
57
57
  const isLoading = ref(false);
58
- if (import.meta.client && generateCheckoutLink) {
58
+ if (!import.meta.server && generateCheckoutLink) {
59
59
  watch(
60
60
  () => [props.lazy, props.productIds, props.subscriptionId, props.metadata, props.embed, props.trialInterval, props.trialIntervalCount, props.locale],
61
61
  async () => {
@@ -89,9 +89,9 @@ export interface ConvexAuthProviderOptions {
89
89
  * @example
90
90
  * ```vue
91
91
  * <script setup lang="ts">
92
- * import { useAuth } from '~/composables/useAuth' // your auth provider
92
+ * import { useAuth } from '~/composables/useMyAuthProvider' // your auth provider
93
93
  *
94
- * const { client } = useNuxtApp().$convex
94
+ * const client = useConvex()
95
95
  * const authState = provideConvexAuth({ client, useAuth })
96
96
  * </script>
97
97
  * ```
@@ -112,11 +112,11 @@ export declare function provideConvexAuth(options: ConvexAuthProviderOptions): C
112
112
  * (`nuxtApp.vueApp.provide`) rather than from a component's setup function.
113
113
  *
114
114
  * When `scope` is provided, all watchers are created inside that
115
- * {@link EffectScope} so callers can dispose them later.
115
+ * `EffectScope` so callers can dispose them later.
116
116
  */
117
117
  export declare function createConvexAuthState(options: ConvexAuthProviderOptions, scope?: EffectScope): ConvexAuthState;
118
118
  /**
119
- * Create a fresh {@link EffectScope} and build a Convex auth state inside it.
119
+ * Create a fresh `EffectScope` and build a Convex auth state inside it.
120
120
  * The scope is returned so the caller can `.stop()` it on teardown.
121
121
  */
122
122
  export declare function createScopedConvexAuthState(options: ConvexAuthProviderOptions): {
@@ -1,24 +1,19 @@
1
1
  import type { InjectionKey } from 'vue';
2
- import { BaseConvexClient } from 'convex/browser';
3
2
  import type { AuthTokenFetcher, BaseConvexClientOptions, ConnectionState, OptimisticUpdate, PaginationStatus, QueryJournal, QueryOptions } from 'convex/browser';
4
3
  import type { Watch as ConvexWatch } from 'convex/react';
5
- import type { ArgsAndOptions, FunctionArgs, FunctionReference, FunctionReturnType, OptionalRestArgs, UserIdentityAttributes } from 'convex/server';
4
+ import type { ArgsAndOptions, FunctionArgs, FunctionReference, FunctionReturnType, OptionalRestArgs } from 'convex/server';
6
5
  import type { Value } from 'convex/values';
7
6
  export type { AuthTokenFetcher, ConnectionState, OptimisticUpdate };
8
7
  /**
9
8
  * A watch on the output of a Convex query function.
10
9
  *
11
10
  * Derived from upstream's `Watch` (per-member docs live there), extended with
12
- * the `@internal` `localQueryLogs`, which is stripped from the published
11
+ * the internal `localQueryLogs`, which is stripped from the published
13
12
  * `convex/react` types but present at runtime.
14
13
  *
15
14
  * @public
16
15
  */
17
16
  export interface Watch<T> extends ConvexWatch<T> {
18
- /**
19
- * @internal
20
- */
21
- localQueryLogs(): string[] | undefined;
22
17
  }
23
18
  /**
24
19
  * A watch on the output of a paginated Convex query function.
@@ -61,10 +56,6 @@ export interface WatchQueryOptions {
61
56
  * name and arguments, this journal will have no effect.
62
57
  */
63
58
  journal?: QueryJournal;
64
- /**
65
- * @internal
66
- */
67
- componentPath?: string;
68
59
  }
69
60
  /**
70
61
  * Options for {@link ConvexVueClient.mutation}.
@@ -101,7 +92,7 @@ export type ConvexLogger = Exclude<BaseConvexClientOptions['logger'], boolean |
101
92
  * This loads reactive queries and executes mutations over a WebSocket.
102
93
  *
103
94
  * In a Nuxt app the client is provided automatically by the plugin and
104
- * available via the {@link useConvex} composable or `useNuxtApp().$convex`.
95
+ * available via the {@link useConvex} composable.
105
96
  *
106
97
  * @public
107
98
  */
@@ -127,13 +118,6 @@ export declare class ConvexVueClient {
127
118
  * it may be canonicalized.
128
119
  */
129
120
  get url(): string;
130
- /**
131
- * Lazily instantiate the `BaseConvexClient` so we don't create the WebSocket
132
- * when server-side rendering.
133
- *
134
- * @internal
135
- */
136
- get sync(): BaseConvexClient;
137
121
  /**
138
122
  * Set the authentication token to be used for subsequent queries and mutations.
139
123
  * `fetchToken` will be called automatically again if a token expires.
@@ -148,10 +132,6 @@ export declare class ConvexVueClient {
148
132
  * Clear the current authentication token if set.
149
133
  */
150
134
  clearAuth(): void;
151
- /**
152
- * @internal
153
- */
154
- setAdminAuth(token: string, identity?: UserIdentityAttributes): void;
155
135
  /**
156
136
  * Construct a new {@link Watch} on a Convex query function.
157
137
  *
@@ -183,32 +163,6 @@ export declare class ConvexVueClient {
183
163
  prewarmQuery<Query extends FunctionReference<'query'>>(queryOptions: QueryOptions<Query> & {
184
164
  extendSubscriptionFor?: number;
185
165
  }): void;
186
- /**
187
- * Construct a new {@link PaginatedWatch} on a Convex paginated query function.
188
- *
189
- * **Not supported in the Vue port — use the {@link usePaginatedQuery}
190
- * composable instead.** Convex's paginated-subscription engine
191
- * (`PaginatedQueryClient`) is not part of the public `convex` exports, so a
192
- * third-party package cannot instantiate it; pagination is handled entirely
193
- * in the composable layer via ordinary {@link watchQuery} subscriptions.
194
- *
195
- * The method is retained for structural parity with
196
- * `ConvexReactClient.watchPaginatedQuery`. It is reachable only if a caller
197
- * passes `paginationOptions` to {@link useConvexQueries} (the React-shaped
198
- * escape hatch); doing so throws this error to fail loudly rather than
199
- * silently mis-subscribe.
200
- *
201
- * Upstream wires {@link usePaginatedQuery_experimental} to this method's
202
- * `PaginatedQueryClient`; the port re-bases that hook on the same manual
203
- * page-management engine as {@link usePaginatedQuery}, so both hooks work
204
- * without ever calling this method (only the experimental single-request
205
- * network path is not reproduced).
206
- *
207
- * PARITY: D-05
208
- *
209
- * @internal
210
- */
211
- watchPaginatedQuery<Query extends FunctionReference<'query'>>(_query: Query, _args: Query['_args'], _options: unknown): PaginatedWatch<FunctionReturnType<Query>>;
212
166
  /**
213
167
  * Execute a mutation function.
214
168
  *
@@ -248,6 +202,7 @@ export declare class ConvexVueClient {
248
202
  * deployment.
249
203
  *
250
204
  * @returns The {@link ConnectionState} with the Convex deployment.
205
+ * @experimental May change in a minor release — see STABILITY.md.
251
206
  */
252
207
  connectionState(): ConnectionState;
253
208
  /**
@@ -261,6 +216,7 @@ export declare class ConvexVueClient {
261
216
  * out what information is most useful. As such this API is considered unstable.
262
217
  *
263
218
  * @returns An unsubscribe function to stop listening.
219
+ * @experimental May change in a minor release — see STABILITY.md.
264
220
  */
265
221
  subscribeToConnectionState(cb: (connectionState: ConnectionState) => void): () => void;
266
222
  /**
@@ -297,11 +253,3 @@ export declare const ConvexClientKey: InjectionKey<ConvexVueClient>;
297
253
  * @public
298
254
  */
299
255
  export declare function useConvex(): ConvexVueClient;
300
- /**
301
- * Inject the Convex client for a composable, throwing the per-composable
302
- * missing-client error when absent — mirrors the checks at the top of
303
- * upstream's `useQuery`/`useMutation`/`useAction`/`useConvexConnectionState`.
304
- *
305
- * @internal
306
- */
307
- export declare function useConvexOrThrow(composableName: string): ConvexVueClient;
@@ -314,6 +314,7 @@ export class ConvexVueClient {
314
314
  * deployment.
315
315
  *
316
316
  * @returns The {@link ConnectionState} with the Convex deployment.
317
+ * @experimental May change in a minor release — see STABILITY.md.
317
318
  */
318
319
  connectionState() {
319
320
  return this.sync.connectionState();
@@ -329,6 +330,7 @@ export class ConvexVueClient {
329
330
  * out what information is most useful. As such this API is considered unstable.
330
331
  *
331
332
  * @returns An unsubscribe function to stop listening.
333
+ * @experimental May change in a minor release — see STABILITY.md.
332
334
  */
333
335
  subscribeToConnectionState(cb) {
334
336
  return this.sync.subscribeToConnectionState(cb);
@@ -0,0 +1,50 @@
1
+ import { type PropType } from 'vue';
2
+ import { type GetStorageUrl } from '../composables/use-storage-url.js';
3
+ import type { StorageId } from '../composables/use-upload.js';
4
+ /**
5
+ * An `<img>` for a file in Convex storage. Resolves the served URL through
6
+ * {@link useStorageUrl} and renders the image once it is known; every other
7
+ * attribute (`alt`, `class`, `loading`, `width`, …) goes onto the `<img>`.
8
+ *
9
+ * - default slot — rendered while the URL is loading or `storageId` is empty
10
+ * - `missing` slot — rendered when the file no longer exists (the query returned `null`)
11
+ *
12
+ * @example
13
+ * ```vue
14
+ * <ConvexImage :get-url="api.files.url" :storage-id="doc.imageId" alt="Cover" class="rounded">
15
+ * <div class="skeleton" />
16
+ * <template #missing><div class="placeholder" /></template>
17
+ * </ConvexImage>
18
+ * ```
19
+ *
20
+ * @public
21
+ */
22
+ export declare const ConvexImage: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
23
+ /** The public `getUrl` query: `{ storageId }` → served URL or `null`. Read once, at setup. */
24
+ getUrl: {
25
+ type: PropType<GetStorageUrl>;
26
+ required: true;
27
+ };
28
+ /** The file to show; `null`/`undefined` renders the default slot. */
29
+ storageId: {
30
+ type: PropType<StorageId | string | null | undefined>;
31
+ default: undefined;
32
+ };
33
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
34
+ [key: string]: any;
35
+ }> | import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
36
+ [key: string]: any;
37
+ }>[] | null, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
38
+ /** The public `getUrl` query: `{ storageId }` → served URL or `null`. Read once, at setup. */
39
+ getUrl: {
40
+ type: PropType<GetStorageUrl>;
41
+ required: true;
42
+ };
43
+ /** The file to show; `null`/`undefined` renders the default slot. */
44
+ storageId: {
45
+ type: PropType<StorageId | string | null | undefined>;
46
+ default: undefined;
47
+ };
48
+ }>> & Readonly<{}>, {
49
+ storageId: string | StorageId | null | undefined;
50
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
@@ -0,0 +1,21 @@
1
+ import { defineComponent, h } from "vue";
2
+ import { useStorageUrl } from "../composables/use-storage-url.js";
3
+ export const ConvexImage = defineComponent({
4
+ name: "ConvexImage",
5
+ inheritAttrs: false,
6
+ props: {
7
+ /** The public `getUrl` query: `{ storageId }` → served URL or `null`. Read once, at setup. */
8
+ getUrl: { type: Object, required: true },
9
+ /** The file to show; `null`/`undefined` renders the default slot. */
10
+ storageId: { type: String, default: void 0 }
11
+ },
12
+ setup(props, { attrs, slots }) {
13
+ const url = useStorageUrl(props.getUrl, () => props.storageId);
14
+ return () => {
15
+ const value = url.value;
16
+ if (value) return h("img", { ...attrs, src: value });
17
+ if (value === null) return slots.missing?.() ?? null;
18
+ return slots.default?.() ?? null;
19
+ };
20
+ }
21
+ });
@@ -26,5 +26,6 @@ import type { ShallowRef } from 'vue';
26
26
  * @returns The current {@link ConnectionState} with the Convex deployment.
27
27
  *
28
28
  * @public
29
+ * @experimental May change in a minor release — see STABILITY.md.
29
30
  */
30
31
  export declare function useConvexConnectionState(): ShallowRef<ConnectionState>;
@@ -32,7 +32,10 @@ export type { PaginatedQueryReference, PaginatedQueryArgs, PaginatedQueryItem, U
32
32
  export declare function usePaginatedQuery<Query extends PaginatedQueryReference>(query: Query, args: MaybeRefOrGetter<PaginatedQueryArgs<Query> | 'skip'>, options: {
33
33
  initialNumItems: number;
34
34
  }): UsePaginatedQueryReturnType<Query>;
35
- /** @internal */
35
+ /**
36
+ * Reset pagination id for tests only, so tests know what it is.
37
+ * @experimental May change in a minor release — see STABILITY.md.
38
+ */
36
39
  export declare function resetPaginationId(): void;
37
40
  /**
38
41
  * Return shape of {@link usePaginatedQuery} — the fields of upstream's
@@ -125,6 +128,7 @@ export declare function insertAtPosition<Query extends PaginatedQueryReference>(
125
128
  * identical observable results (`results`/`data`, `status`, `loadMore`).
126
129
  *
127
130
  * @public
131
+ * @experimental May change in a minor release — see STABILITY.md.
128
132
  */
129
133
  export declare function usePaginatedQuery_experimental<Query extends PaginatedQueryReference>(query: Query, args: MaybeRefOrGetter<PaginatedQueryArgs<Query> | 'skip'>, options: {
130
134
  initialNumItems: number;
@@ -1,7 +1,7 @@
1
1
  import { getFunctionName } from "convex/server";
2
2
  import { ConvexError, compareValues, convexToJson } from "convex/values";
3
3
  import { computed, shallowRef, toValue } from "vue";
4
- import { useConvex } from "../client.js";
4
+ import { useConvexOrThrow } from "../client.js";
5
5
  import { useConvexQueries } from "./use-queries.js";
6
6
  const splitQuery = (key, splitCursor, continueCursor) => (prevState) => {
7
7
  const queries = { ...prevState.queries };
@@ -98,7 +98,7 @@ function usePaginatedQueryInternal(query, args, options) {
98
98
  `\`options.initialNumItems\` must be a positive number. Received \`${initialOptions?.initialNumItems}\`.`
99
99
  );
100
100
  }
101
- const convex = useConvex();
101
+ const convex = useConvexOrThrow("usePaginatedQuery");
102
102
  const logger = convex.logger;
103
103
  function createInitialState(q, currentArgs, skip, initialNumItems) {
104
104
  const id = nextPaginationId();
@@ -6,6 +6,7 @@ export type OptionalRestArgsOrSkip<FuncRef extends FunctionReference<any>> = Fun
6
6
  * Result returned by object-form {@link useQuery_experimental}.
7
7
  *
8
8
  * @public
9
+ * @experimental May change in a minor release — see STABILITY.md.
9
10
  */
10
11
  export type UseQueryResult<QueryResult, ThrowOnError extends boolean = false> = ConvexUseQueryResult<QueryResult, ThrowOnError>;
11
12
  type UseQueryOptions<Query extends FunctionReference<'query'>, ThrowOnError extends boolean> = {
@@ -80,6 +81,7 @@ export declare function useQuery<Query extends FunctionReference<'query'>>(query
80
81
  * {@link UseQueryResult} object.
81
82
  *
82
83
  * @public
84
+ * @experimental May change in a minor release — see STABILITY.md.
83
85
  */
84
86
  export declare function useQuery_experimental<Query extends FunctionReference<'query'>, ThrowOnError extends boolean = false>(options: UseQueryOptions<Query, ThrowOnError>): ComputedRef<UseQueryResult<Query['_returnType'], ThrowOnError>>;
85
87
  /** @public */
@@ -1,15 +1 @@
1
- import { type ShallowRef } from 'vue';
2
- /**
3
- * Composable used for safely managing subscriptions in concurrent mode.
4
- *
5
- * In order to avoid removing and re-adding subscriptions each time this composable is called,
6
- * the parameters passed to this composable should be memoized in some way–
7
- * either by wrapping the entire params object with useMemo()
8
- * or by wrapping the individual callbacks with useCallback().
9
- *
10
- * @internal
11
- */
12
- export declare function useSubscription<Value>({ getCurrentValue, subscribe, }: {
13
- getCurrentValue: () => Value;
14
- subscribe: (callback: () => void) => () => void;
15
- }): ShallowRef<Value>;
1
+ export {};
@@ -40,8 +40,8 @@ export interface UseUploadQueueOptions {
40
40
  /** Called once every queued item has settled (succeeded or failed). */
41
41
  onComplete?: (items: UploadQueueItem[]) => void;
42
42
  }
43
- /** Accepted inputs to {@link VueUploadQueue.enqueue}. */
44
- type EnqueueInput = Blob | Blob[] | FileList | null | undefined;
43
+ /** Accepted inputs to {@link VueUploadQueue.enqueue}. @public */
44
+ export type EnqueueInput = Blob | Blob[] | FileList | null | undefined;
45
45
  /**
46
46
  * The reactive queue returned by {@link useUploadQueue}.
47
47
  *
@@ -114,4 +114,3 @@ export interface VueUploadQueue {
114
114
  export declare function useUploadQueue(generateUploadUrl: GenerateUploadUrl, options?: UseUploadQueueOptions): VueUploadQueue;
115
115
  /** @public */
116
116
  export declare const useConvexUploadQueue: typeof useUploadQueue;
117
- export {};